React useReducer+useContext无法获取映射生成输入框的值求助
修复React useReducer动态输入框的状态更新问题
核心问题分析
你的代码存在三个关键错误:
- 新增字段结构错误:
addaction里新增的对象嵌套了多余的fields属性,导致状态结构混乱 - 更新字段逻辑错误:
changeaction直接把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 };
关键修复点说明
- add action:直接向
fields数组添加{ units: "" },保持和初始字段一致的结构,避免嵌套层级错误 - change action:
- 先复制原
fields数组,避免直接修改原状态 - 找到对应索引的字段,复制该对象并更新
units值,保证状态更新的不可变性 - 返回新的状态对象,替换
fields数组
- 先复制原
- 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
相关产品推荐
相关产品推荐

