React表单食材字段异常:输入字符逐次追加而非完整值
问题描述
开发全栈Web应用(MongoDB+Node.js+Express+React),支持创建餐食、录入食材、编写制作步骤及烹饪时长功能。MongoDB模型中ingredients设为数组类型,Postman测试后端接口正常,但React表单中填写食材时出现异常:输入“salt”,最终保存的数组为[s,sa,sal,salt]。
原因分析
- 初始状态类型错误:
initialState中ingredients被设为空字符串"",而非数组类型,导致后续状态更新逻辑混乱。 - 状态更新逻辑错误:reducer的
SET_INGREDIENTS动作每次将输入框的实时值追加到数组中,而非对应单个输入项更新;且多个食材输入框共用同一个更新函数,每输入一个字符就触发一次数组追加。 - 输入框绑定错误:第一个食材输入框将
value绑定到state.ingredients(数组),会自动将数组转为字符串显示,同时加剧了状态更新的异常。
解决方案
1. 修正初始状态的食材类型
将initialState中的ingredients改为数组,对应三个输入框的初始空值:
const initialState = { name: "", minutes: "", directions: "", ingredients: ["", "", ""] // 三个输入框对应三个数组项 }
2. 调整Reducer的状态更新逻辑
修改动作类型和处理逻辑,支持按索引更新单个食材项:
// 更新ACTIONS定义 const ACTIONS = { SET_NAME: "setName", SET_MINUTES: "setMinutes", SET_DIRECTIONS: "setDirections", SET_INGREDIENT: "setIngredient" // 改为单个食材更新 } // 更新reducer函数 const reducer = (state, action) => { switch (action.type) { case ACTIONS.SET_NAME: return { ...state, name: action.payload } case ACTIONS.SET_MINUTES: return { ...state, minutes: action.payload } case ACTIONS.SET_DIRECTIONS: return { ...state, directions: action.payload } case ACTIONS.SET_INGREDIENT: // 复制原数组,修改对应索引的项 const updatedIngredients = [...state.ingredients]; updatedIngredients[action.payload.index] = action.payload.value; return { ...state, ingredients: updatedIngredients } default: return state } }
3. 修改输入框的事件处理函数
创建支持索引的食材更新函数,区分不同输入框的状态:
const handleIngredientChange = (index, e) => { dispatch({ type: ACTIONS.SET_INGREDIENT, payload: { index: index, value: e.target.value } }) }
4. 绑定输入框到对应状态项
每个食材输入框绑定数组中对应索引的值和更新函数:
<div style={FormStyle.inputDiv}> <p>Ingredient(s) - Optional</p> <FormControl> <InputLabel>Ingredient One</InputLabel> <OutlinedInput value={state.ingredients[0]} onChange={(e) => handleIngredientChange(0, e)} style={FormStyle.input} /> </FormControl> <FormControl> <InputLabel>Ingredient Two</InputLabel> <OutlinedInput value={state.ingredients[1]} onChange={(e) => handleIngredientChange(1, e)} style={FormStyle.input} /> </FormControl> <FormControl> <InputLabel>Ingredient Three</InputLabel> <OutlinedInput value={state.ingredients[2]} onChange={(e) => handleIngredientChange(2, e)} style={{width: "20rem",marginBottom: "2rem" }} /> </FormControl> </div>
5. 可选:过滤空食材项(避免提交空值)
在表单提交时过滤掉空或仅含空格的食材字符串:
const handleSubmit = (e) => { e.preventDefault(); // 过滤掉空或仅含空格的食材 const submitData = { ...state, ingredients: state.ingredients.filter(item => item.trim() !== "") }; onSubmitProps(submitData); }
内容的提问来源于stack exchange,提问作者PEACE IKECHUKWU
相关产品推荐
相关产品推荐

