React中如何管理对象数组状态,实现表单属性更新与数组元素递增
解决方案
实现逻辑
- 给通用表单配置项添加
field字段,关联stocks对象对应的属性名 - 父组件封装状态更新函数,通过「表单下标+字段名」精准定位到需要修改的属性,更新stocks数组
- 遍历生成每个表单时,动态为表单元素绑定对应的值和更新回调
- 新增表单功能直接修改stocks数组即可自动渲染空白表单
修改后代码
父组件 AddStocksSection
import { useState } from "react"; import SectiontWrapper from "../../primitives/section-wrapper"; import SectionHeader from "../../primitives/section-header"; import ExpandableForm from "../../constructs/expandable-form"; const AddStocksSection = () => { const [stocks, setStocks] = useState([ { market: "", stock: "", amount: "", }, ]); // 表单配置新增field字段关联对应属性 const formElements = [ { label: "Select a market", placeholder: "Select", required: true, disabled: "", type: "select", field: "market", options: [ { name: "Select", value: "select", }, { name: "AEX", value: "aex", }, ], }, { label: "Select a stock", placeholder: "Select", required: true, disabled: "", type: "select", field: "stock", options: [ { name: "Select", value: "select", }, { name: "Googl", value: "googl", }, ], }, { label: "How many do you have", placeholder: "100", required: true, disabled: "", type: "number", field: "amount", }, ]; // 表单值更新处理函数 const handleStockChange = (formIndex, field, value) => { setStocks(prevStocks => { const updatedStocks = [...prevStocks]; updatedStocks[formIndex][field] = value; return updatedStocks; }); }; // 新增空白表单 const addNewStockForm = () => { setStocks(prev => [...prev, { market: "", stock: "", amount: "" }]); }; return ( <SectiontWrapper> <SectionHeader>Add some stocks</SectionHeader> {stocks.map((stock, i) => ( <ExpandableForm key={i} expanded={false} // 动态生成当前表单专属的配置项,绑定对应值和回调 formElements={formElements.map(el => ({ ...el, value: stock[el.field], onChange: (e) => handleStockChange(i, el.field, e.target.value) }))} addStock={addNewStockForm} /> ))} </SectiontWrapper> ); }; export default AddStocksSection;
子组件 ExpandableForm
import { FormWrapper, ButtonGroup, FormContainer, } from "./expandable-form-style"; import ButtonOutlined from "../../primitives/button-outlined"; import ButtonSolid from "../../primitives/button-solid"; import Loader from "../loader"; import getFormElement from "../../../tools/getFormElement"; const ExpandableForm = ({ submitForm, isDisabled, formElements, isLoading, expanded, addStock // 接收父组件传的新增表单方法 }) => { return ( <FormWrapper expanded={expanded}> <FormContainer> {formElements.map((formElement, i) => { const FormElement = getFormElement(formElement.type); return ( <FormElement key={i} label={formElement.label} placeholder={formElement.placeholder} value={formElement.value} onChange={formElement.onChange} disabled={formElement.disabled} type={formElement.type} options={formElement.options} /> ); })} <ButtonGroup> <ButtonOutlined disabled={isLoading} color="venetianRed"> Skip </ButtonOutlined> <ButtonSolid onClick={addStock} // 绑定新增表单回调 disabled={isLoading || isDisabled} color="yellowGreen" > Add </ButtonSolid> <ButtonSolid onClick={() => submitForm()} disabled={isLoading || isDisabled} color="royalVessel" > {isLoading ? <Loader /> : "Next"} </ButtonSolid> </ButtonGroup> </FormContainer> </FormWrapper> ); }; export default ExpandableForm;
内容的提问来源于stack exchange,提问作者Ricardo de Vries
相关产品推荐
相关产品推荐

