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

React useReducer+useContext无法获取映射生成输入框的值求助

修复React useReducer动态输入框的状态更新问题

核心问题分析

你的代码存在三个关键错误:

  • 新增字段结构错误:add action里新增的对象嵌套了多余的fields属性,导致状态结构混乱
  • 更新字段逻辑错误:change action直接把state解构为数组,完全偏离了原有的状态结构(原state是包含fields数组的对象)
  • 更新函数依赖错误:handleUpdateField里使用了initialState而非当前的inputField状态,导致无法正确更新最新输入值

修正后的完整代码

import { createContext, useContext, useReducer } from "react";

const QuoteContext = createContext();

const initialState = {
  fields: [{ units: "" }]
};

function reducer(state, action) {
  switch (action.type) {
    case "add":
      return {
        ...state,
        fields: [...state.fields, { units: "" }] // 直接添加和初始结构一致的字段对象
      };

    case "change":
      // 复制原fields数组,更新对应索引的units值(遵循不可变更新原则)
      const updatedFields = [...state.fields];
      updatedFields[action.index] = { ...updatedFields[action.index], units: action.value };
      return {
        ...state,
        fields: updatedFields
      };

    default:
      throw new Error("Unknown action type");
  }
}

function QuoteProvider({ children }) {
  const [inputField, setInputField] = useReducer(reducer, initialState);

  const handleAddField = () => {
    setInputField({ type: "add" });
  };

  const handleUpdateField = (e, index) => {
    setInputField({
      type: "change",
      index,
      value: e.target.value
    });
  };

  // 将状态和操作方法传入上下文,供子组件调用
  return (
    <QuoteContext.Provider value={{ inputField, handleAddField, handleUpdateField }}>
      {children}
    </QuoteContext.Provider>
  );
}

export { QuoteContext, QuoteProvider };

关键修复点说明

  1. add action:直接向fields数组添加{ units: "" },保持和初始字段一致的结构,避免嵌套层级错误
  2. change action:
    • 先复制原fields数组,避免直接修改原状态
    • 找到对应索引的字段,复制该对象并更新units值,保证状态更新的不可变性
    • 返回新的状态对象,替换fields数组
  3. handleUpdateField:通过reducer处理状态更新,传递输入框索引和当前值给action,确保更新目标输入框的正确值

子组件使用示例(参考)

import { useContext } from "react";
import { QuoteContext } from "./QuoteProvider";

function InputFields() {
  const { inputField, handleAddField, handleUpdateField } = useContext(QuoteContext);

  return (
    <div>
      {inputField.fields.map((field, index) => (
        <input
          key={index}
          value={field.units}
          onChange={(e) => handleUpdateField(e, index)}
          placeholder="输入内容"
        />
      ))}
      <button onClick={handleAddField}>添加输入框</button>
    </div>
  );
}

export default InputFields;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:30:04