从服务端拉取动态表单字段时如何使用useState管理状态?
解决方案
你不能在循环中调用useState,这违反React Hook的调用规则(Hook只能在组件顶层作用域调用,不能放入循环、条件判断、子函数内),同时JS也不支持直接把字符串当作变量名来赋值状态更新函数。正确的实现方式是用单个对象类型的状态统一管理所有表单字段的值,以从数据库拿到的item_id作为对象的键名:
- 定义表单状态,拉取到字段配置后初始化默认值
import { useState, useEffect } from 'react' // 统一存储所有表单字段值 const [formValues, setFormValues] = useState({}) // 从Firestore拉取到formfield配置后,初始化空的字段值 useEffect(() => { if (!formfield?.length) return const initialState = formfield.reduce((acc, field) => { // 可以根据字段配置设置默认值,没有的话默认为空字符串 acc[field.item_id] = field.default_value || '' return acc }, {}) setFormValues(initialState) }, [formfield])
- 编写通用的输入变更处理函数
const handleFieldChange = (e) => { const fieldId = e.target.id const inputValue = e.target.value setFormValues(prev => ({ ...prev, [fieldId]: inputValue })) }
- 修改动态渲染的输入框绑定逻辑,同时修正你原代码中变量名混淆的问题(原代码里混用
item和form_item会导致报错)
{ formfield && formfield .filter(items => items.type === 'text') .sort((a,b) => a.order_by - b.order_by) .map(item => { return ( <div className="input-field mb-40" key={item.item_id}> <input placeholder={item.place_holder} type="text" id={item.item_id} value={formValues[item.item_id] || ''} required={item.required} onChange={handleFieldChange} /> <label htmlFor={item.item_id} className="active fnt-16"> {item.label} </label> </div> ) }) }
后续你要提交表单的时候,直接读取formValues对象就能拿到所有字段的输入值,完全适配动态增减的字段配置。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

