類似下面這種功能:
點擊添加表增加一行,刪除表刪除一行,
思路:將這個表單抽成一個單獨的組件,維護一個時間戳數組,這個數組的作用就是通過map循環來生成動態表單,每次點擊添加就在數組里添加一個時間戳。最終遍歷有幾個item就渲染幾個表單。
實現:
dynamic.js 動態表單 子組件
import React from 'react'; import { Select } from 'antd'; export default function DynamicForm(selectOptions1, selectOptions2) { return ( <>
<span>業務線分組:</span>
<Select defaultValue="1" style={{ width: 120, marginRight: 20 }} options={selectOptions1}>
</Select>
<span>數據庫:</span>
<Select defaultValue="1" style={{ width: 120, marginRight: 20 }} options={selectOptions2}>
</Select>
<span>表名稱:</span>
<Select defaultValue="1" style={{ width: 120, marginRight: 20 }} options={selectOptions2}>
</Select>
</>
); }
index.js 父組件
/* eslint-disable multiline-ternary */ import React, { useState, useEffect} from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import { Form, Input, Button, Radio, Select } from 'antd'; import {getRuleDetailApi} from '../../api/rule.api'; import '../../assets/common.less'; import dynamicForm from './DynamicForm'; const { Option } = Select; export default function AddNewMonitorRule(props) { const history = useHistory(); const location = useLocation(); const [ruleType, setRuleType] = useState(1); const [dynamicFormItem, setDynamicFormItem] = useState([]); const handleRuleTypeChange = (e) => { setRuleType(e.target.value); }; // 添加表
const addDynamicForm = (e) => { e.preventDefault(); const newDynamicForm = dynamicFormItem.concat([Date.now()]); setDynamicFormItem(newDynamicForm); console.log(newDynamicForm); }; // 刪除表
const removeDynamicFormItem = (index) => { let tempDynamicFormItem = [...dynamicFormItem]; // 先拷貝一份,再修改,直接修改原數組react會認為是沒有變化,所以頁面不更新
tempDynamicFormItem.splice(index, 1); setDynamicFormItem(tempDynamicFormItem); // setDynamicFormItem((state) => {
// console.log(state);
// // let tempDynamicFormItem = state.concat(); // 先拷貝一份,再修改,直接修改原數組react會認為是沒有變化,所以頁面不更新react中數組,如果引用地址不變,是不觸發重新渲染的,但是值是設置進去了
// state.splice(index, 1);
// return [...state];
// });
};return ( <Form className="container" labelCol={{ span: 4 }} wrapperCol={{ span: 14 }}>
<Form.Item label="表選擇">
<div> {dynamicForm(lineGropOptions, dataBaseOptions, tableNameOptions)} <Button onClick={addDynamicForm}>添加表</Button>
</div>
{dynamicFormItem.map((item, index) => { return ( <div key={item} style={{ marginTop: 20 }}> {dynamicForm(lineGropOptions, dataBaseOptions, tableNameOptions)} <Button onClick={() => { removeDynamicFormItem(index); }}> 刪除表 </Button>
</div>
); })} </Form.Item>
</Form>
); }
踩坑日記:
1.useState修改state數據不發生變化:
原因是在原數組上修改了,react檢測不到變化,需要拷貝一份新的數組,修改完新數組,再用新數組修改state的值,也就是新舊state的引用地址必須不一樣才行。
2.刪除表,采用index作為key導致頁面更新復用了之前的item,比如我打算刪除第一個,但是因為 key = index === 0,react就會比較發現 之前和現在都有個 key === 0 的dom節點,那就會復用之前的dom,雖然頁面上確實少了一項,但是你發現第一項被復用了,給人感覺就是刪除了最后一項。