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

React跨组件使用useReducer管理表单状态的问题求助

React状态提升与useReducer使用错误修复

问题概述

在React项目中执行以下操作时出现错误:

  • 将BookingForm组件的availableTimes状态提升至Main组件
  • 使用useReducer替代useState管理该状态

选择日期时抛出**"dispatch is not a function / initializeTimes is not a function"**错误。

错误原因分析

  1. 组件未渲染导致Props未传递:Main.js中showBookingForm被设置为false,BookingForm未被渲染;若手动改为true但未正确传递dispatch,会导致dispatch为undefined,调用时报错。
  2. Reducer逻辑缺失必要参数:调用dispatch时未传入选中日期与新的可用时间,reducer返回undefined,导致availableTimes状态失效,后续map调用出错。
  3. 初始化函数用法不规范:useReducer直接调用初始化函数生成初始值,虽能运行,但不符合标准用法,易引发后续修改错误。

修复后的代码

Main.js

import React, {useReducer} from 'react';
// 保留原有导入内容
import BookingForm from './BookingForm';

function Main() {
    // 初始化可用时间的函数
    function initializeTimes() {
        return [
          '17:00',
          '18:00',
          '19:00',
          '20:00',
          '21:00',
          '22:00'
        ];
    }

    // 根据日期更新可用时间的reducer逻辑
    function updateTimes(state, action) {
        switch (action.type) {
            case 'update_times':
                const selectedDate = action.date;
                // 模拟业务逻辑:周末提供更多时段
                if (new Date(selectedDate).getDay() === 0 || new Date(selectedDate).getDay() === 6) {
                    return ['16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'];
                } else {
                    return initializeTimes();
                }
            default:
                return state;
        }
    }

    // 标准useReducer初始化方式:第三个参数为初始化函数
    const [availableTimes, dispatch] = useReducer(updateTimes, undefined, initializeTimes);

    // 确保BookingForm被渲染
    const showBookingForm = true;

    return (
        <div>
            {showBookingForm && (<BookingForm availableTimes={availableTimes} dispatch={dispatch}/>)}
            
            {/* 保留原有Main组件其余代码 */}
        </div>
    );
}

export default Main;

BookingForm.js

import React, { useState } from 'react';

function BookingForm({ availableTimes = [], dispatch }) {
    const [date, setDate] = useState('');
    const [time, setTime] = useState('17:00');
    const [guests, setGuests] = useState(1);
    const [occasion, setOccasion] = useState('Birthday');

    const handleFormSubmit = (event) => {
        event.preventDefault();
        console.log('Form submitted:', { date, time, guests, occasion });
    };

    const handleDateChange = (e) => {
        const selectedDate = e.target.value;
        setDate(selectedDate);
        // 传入选中日期参数给reducer
        dispatch({type: "update_times", date: selectedDate});
      };

    return (
        <form style={{ display: 'grid', maxWidth: '200px', gap: '20px' }} onSubmit={handleFormSubmit}>
            <label htmlFor="res-date">Choose date</label>
            <input type="date" id="res-date" value={date} onChange={handleDateChange} />
            <label htmlFor="res-time">Choose time</label>
            <select id="res-time" value={time} onChange={(e) => setTime(e.target.value)}>
                {availableTimes.map((availableTime) => (
                    <option key={availableTime} value={availableTime}>
                        {availableTime}
                    </option>
                ))}
            </select>
            <label htmlFor="guests">Number of guests</label>
            <input type="number" placeholder="1" min="1" max="10" id="guests" value={guests} onChange={(e) => setGuests(e.target.value)} />
            <label htmlFor="occasion">Occasion</label>
            <select id="occasion" value={occasion} onChange={(e) => setOccasion(e.target.value)}>
                <option value="Birthday">Birthday</option>
                <option value="Anniversary">Anniversary</option>
            </select>
            <input type="submit" value="Make Your reservation" />
        </form>
    );
}

export default BookingForm;

验证步骤

  1. 启动项目,确认BookingForm正常渲染
  2. 选择不同日期(工作日/周末),查看下拉框中的可用时间是否按预期更新
  3. 检查浏览器控制台,确认无"dispatch is not a function"或其他相关错误

内容的提问来源于stack exchange,提问作者Τάσος Τσιαμίτας

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:24:55