You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React餐厅预订应用:API返回的bookingId无法在结果页正常渲染

问题分析与解决方案

问题根源

  1. 表单页useParams无效:BookingForm页面的路由中并未定义id参数,所以const { id } = useParams();拿到的始终是undefined,点击链接自然会跳转到/booking/undefined。
  2. 未捕获预订返回ID:提交表单成功后,没有从API返回结果中提取新生成的bookingId,而是错误使用了不存在的路由参数。

修复步骤

1. 修改BookingForm.tsx代码

移除无用的useParams,改用useNavigate实现跳转,同时存储新生成的预订ID:

import axios from "axios";
import { useEffect, useState } from "react";
import { ChangeEvent, SyntheticEvent } from "react";
import { Link, useNavigate } from "react-router-dom";

import { IBookings } from "../models/IBookings";

export const BookingForm = () => {
    const navigate = useNavigate();
    const [restaurants, setRestaurants] = useState<IBookings[]>([]);
    const [newBookingId, setNewBookingId] = useState<string | null>(null);

    const [addBooking, setAddBooking] = useState({
        restaurantId: '',
        date: '',
        time: '',
        numberOfGuests: 0,
        customer: {
            name: '',
            lastname: '',
            email: '',
            phone: ''
        }
    });

    useEffect(() => {
        getRestaurants();
    }, []);

    const getRestaurants = async () => {
        try {
            const response = await axios.get<IBookings[]>(
                `https://school-restaurant-api.azurewebsites.net/restaurant/65c6276ee125e85f5e15b79f`
            );
            setRestaurants(response.data);
        } catch (error) {
            console.error("Error fetching restaurants:", error);
        }
    };

    const handleInputChange = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
        const { name, value } = e.target;
        if (name.startsWith("customer.")) {
            setAddBooking(prevState => ({
                ...prevState,
                customer: {
                    ...prevState.customer,
                    [name.split('.')[1]]: value
                }
            }));
        } else {
            const newValue = name === 'numberOfGuests' ? parseInt(value) : value;
            setAddBooking(prevState => ({
                ...prevState,
                [name]: newValue
            }));
        }
    };

    const onSubmit = (e: SyntheticEvent<HTMLFormElement, SubmitEvent>) => {
        e.preventDefault();
        axios.post("https://school-restaurant-api.azurewebsites.net/booking/create", addBooking)
            .then((response) => {
                console.log('New booking created successfully:', response.data);
                // 从API返回结果中提取预订ID(字段名请根据实际返回调整)
                const bookingId = response.data.id;
                setNewBookingId(bookingId);
                // 自动跳转到结果页
                navigate(`/booking/${bookingId}`);
            })
            .catch((error) => {
                console.error('Error creating booking:', error);
            });
    };

    return (
        <div className="m-4 border-8 border-pink-600">
            <h2>Make your reservation</h2>
            <form action="" onSubmit={onSubmit}>
                {/* 表单输入部分保持不变 */}
                <div>
                    <label>Choose restaurant</label>
                    <select
                        name="restaurantId"
                        value={addBooking.restaurantId}
                        onChange={handleInputChange}>
                    
                        <option value="0">None</option>
                        <option value="65c6276ee125e85f5e15b79f">Happy Dumpling</option>

                    </select>
                </div>

                <div>
                    <label>Date</label>
                    <input
                        type="date"
                        placeholder="Add Date"
                        name="date"
                        value={addBooking.date}
                        onChange={handleInputChange}
                    />
                </div>
                <div>
                    <label>Time</label>
                    <select
                        name="time"
                        value={addBooking.time}
                        onChange={handleInputChange}
                    >
                        <option value="0">0</option>
                        <option value="18.00">18:00</option>
                        <option value="21.00">21:00</option>
                    </select>
                </div>
                <div>
                    <label>How many seats</label>
                    <select
                        name="numberOfGuests"
                        value={addBooking.numberOfGuests}
                        onChange={handleInputChange}
                    >
                        <option value="0">0</option>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                    </select>
                </div>
                <div>
                    <label>Name</label>
                    <input
                        type="text"
                        placeholder="Name"
                        name="customer.name"
                        value={addBooking.customer.name}
                        onChange={handleInputChange}
                    />
                </div>
                <div>
                    <label>LastName</label>
                    <input
                        type="text"
                        placeholder="LastName"
                        name="customer.lastname"
                        value={addBooking.customer.lastname}
                        onChange={handleInputChange}
                    />
                </div>
                <div>
                    <label>Email</label>
                    <input
                        type="text"
                        placeholder="Email"
                        name="customer.email"
                        value={addBooking.customer.email}
                        onChange={handleInputChange}
                    />
                </div>
                <div>
                    <label>Phone</label>
                    <input
                        type="text"
                        placeholder="Phone"
                        name="customer.phone"
                        value={addBooking.customer.phone}
                        onChange={handleInputChange}
                    />
                </div>
                <button className="btn btn-block" type="submit" value="Save Task">
                    Book a table
                </button>
                <br />
                {/* 仅在创建成功后显示链接 */}
                {newBookingId && (
                    <Link to={`/booking/${newBookingId}`}>Se din bokning här</Link>
                )}
            </form>
        </div>
    );
};

2. 确认路由配置有效性

确保你的路由规则包含/booking/:id,示例如下:

import { Routes, Route } from 'react-router-dom';
import { BookingForm } from './BookingForm';
import { BookingRender } from './BookingRender';

function App() {
  return (
    <Routes>
      <Route path="/" element={<BookingForm />} />
      <Route path="/booking/:id" element={<BookingRender />} />
    </Routes>
  );
}

关键说明

  • 表单提交成功后,必须从response.data中提取API返回的预订ID(字段名可能是id或bookingId,请根据实际返回调整)。
  • 移除表单页中无用的useParams,因为该页面路由无id参数,无法获取有效值。
  • 可选择自动跳转或创建成功后显示链接,两种方式都能确保传递正确的bookingId。

内容的提问来源于stack exchange,提问作者gritoverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 22:12:08