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

如何用useReducer实现表单中根据选中日期更新可用时间?

问题:如何实现根据选中日期更新表单时间选项的updateTimes函数?

需求说明

步骤2:更新BookingForm以根据选中日期显示可用时间

  1. 将availableTimes状态改为reducer
  2. 在Main组件中创建updateTimes函数,根据选中日期更改availableTimes(目前可先返回固定时间)
  3. 创建initializeTimes函数生成availableTimes初始状态
  4. 使用useReducer管理availableTimes状态
  5. 更新BookingForm,在日期字段变更时触发dispatch更新时间

现有代码

表单reducer

const formReducer= (state, event) => {
    return {
        ...state,
        [event.name]: event.value
    }
}

BookingForm组件

function Bookingform(props){
    const [formData, setFormData] = useReducer(formReducer, {});
    const [submitting, setSubmitting] = useState();
    
    const times = [
        {value: "17:00", text: "17:00" },
        {value: "18:00", text: "18:00" },
        {value: "19:00", text: "19:00" },
        {value: "20:00", text: "20:00" },
        {value: "21:00", text: "21:00" },
        {value: "22:00", text: "22:00" },
      ]
   

    const handleSubmit = (e) => {
        e.preventDefault();
        setSubmitting(true);
        props.onSubmit(formData);
        setTimeout (() => {
            setSubmitting(false);
        }, 3000)
    };

    const handleChange = event => {
        const isCheckbox = event.target.type === "checkbox";
        setFormData({
            name: event.target.name,
            value: event.target.value,
            value: isCheckbox ? event.target.checked : event.target.value,
            
        });
    }


    return (
        <div className="Wrapper">
            <h1>Reserve a Table</h1>
            <form onSubmit={handleSubmit}>
                <fieldset>
                    <field name="field" value={field}>
                    <label>
                        <p>Time</p>
                        <select name="Time" onChange={handleChange}>
                            {times.map((option, index) => (
                            <option key={index} value={option.value}>
                            {option.text}
                            </option>
                            ))}

                        </select>
                    </label>
                    <label>
                        <p>Date</p>
                        <input type="date" name="Date" onChange={handleChange}/>
                    </label>
                    <label>
                        <p>Guests</p>
                        <input type="number" name="Count" min="1" max="9" onChange={handleChange} step="1"/>
                    </label>
                    <label>
                    <p>Choose Occasion</p>
                        <select name="Occasion" onChange={handleChange}>
                            <option>Anniversary</option>
                            <option>Birthday</option>
                        </select>
                    </label>
                    <button type="submit">Submit</button>
                 </field>
                </fieldset>

            </form>
        </div>
    )

}

分步实现方案

1. 定义时间状态的reducer函数

在Main组件中创建初始化和更新时间的函数:

// 生成初始可用时间列表
const initializeTimes = () => [
  {value: "17:00", text: "17:00" },
  {value: "18:00", text: "18:00" },
  {value: "19:00", text: "19:00" },
  {value: "20:00", text: "20:00" },
  {value: "21:00", text: "21:00" },
  {value: "22:00", text: "22:00" },
];

// 处理时间状态更新的reducer
const updateTimes = (state, action) => {
  switch(action.type) {
    case 'UPDATE_TIMES':
      // 这里可根据action.payload(选中的日期)编写动态时间逻辑
      // 当前先返回固定时间,后续可扩展(比如周末多开放时段)
      return initializeTimes();
    default:
      // 未知action类型时返回原状态
      return state;
  }
};

2. 在Main组件中用useReducer管理时间状态

初始化reducer,并将时间状态和更新函数传递给BookingForm:

import { useReducer } from 'react';

function Main() {
  // 用useReducer初始化时间状态,第三个参数是初始化函数
  const [availableTimes, dispatch] = useReducer(updateTimes, undefined, initializeTimes);

  return (
    <div>
      <Bookingform 
        availableTimes={availableTimes}
        // 传递日期变更时触发的函数,用于dispatch更新时间
        onDateChange={(selectedDate) => {
          dispatch({ type: 'UPDATE_TIMES', payload: selectedDate });
        }}
        // 保留原有的onSubmit回调
        onSubmit={/* 你的提交逻辑 */}
      />
    </div>
  );
}

3. 修改BookingForm组件适配新状态

移除硬编码的times数组,改用父组件传入的availableTimes,并在日期变更时触发更新:

import { useReducer, useState } from 'react';

const formReducer= (state, event) => {
    return {
        ...state,
        [event.name]: event.value
    }
}

function Bookingform(props){
    const [formData, setFormData] = useReducer(formReducer, {});
    const [submitting, setSubmitting] = useState(false);
    
    // 从props获取可用时间
    const times = props.availableTimes;

    const handleSubmit = (e) => {
        e.preventDefault();
        setSubmitting(true);
        props.onSubmit(formData);
        setTimeout (() => {
            setSubmitting(false);
        }, 3000)
    };

    const handleChange = event => {
        const isCheckbox = event.target.type === "checkbox";
        const value = isCheckbox ? event.target.checked : event.target.value;
        
        setFormData({
            name: event.target.name,
            value: value,
        });

        // 检测日期字段变更,触发父组件的时间更新
        if(event.target.name === "Date") {
            props.onDateChange(event.target.value);
        }
    }

    return (
        <div className="Wrapper">
            <h1>Reserve a Table</h1>
            <form onSubmit={handleSubmit}>
                <fieldset>
                    {/* 移除原错误的<field>标签 */}
                    <label>
                        <p>Time</p>
                        <select name="Time" onChange={handleChange} value={formData.Time || ""}>
                            {times.map((option, index) => (
                            <option key={index} value={option.value}>
                            {option.text}
                            </option>
                            ))}
                        </select>
                    </label>
                    <label>
                        <p>Date</p>
                        <input type="date" name="Date" onChange={handleChange} value={formData.Date || ""}/>
                    </label>
                    <label>
                        <p>Guests</p>
                        <input type="number" name="Count" min="1" max="9" onChange={handleChange} step="1" value={formData.Count || 1}/>
                    </label>
                    <label>
                    <p>Choose Occasion</p>
                        <select name="Occasion" onChange={handleChange} value={formData.Occasion || ""}>
                            <option value="Anniversary">Anniversary</option>
                            <option value="Birthday">Birthday</option>
                        </select>
                    </label>
                    <button type="submit" disabled={submitting}>
                        {submitting ? "Submitting..." : "Submit"}
                    </button>
                </fieldset>
            </form>
        </div>
    )
}

关键细节说明

  • 状态提升:将时间状态放在Main组件管理,符合React单向数据流原则,方便后续扩展(比如从API拉取可用时间)。
  • reducer逻辑:updateTimes通过action类型区分操作,后续只需修改case分支,就能实现根据不同日期返回不同时间的逻辑。
  • 表单优化:给所有表单控件添加value绑定formData,转为受控组件,避免状态不一致;修复原代码中无效的<field>标签;添加提交按钮禁用状态,防止重复提交。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:50:40