类似下面这种功能:
点击添加表增加一行,删除表删除一行,
思路:将这个表单抽成一个单独的组件,维护一个时间戳数组,这个数组的作用就是通过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={{ 120, marginRight: 20 }} options={selectOptions1}>
</Select>
<span>数据库:</span>
<Select defaultValue="1" style={{ 120, marginRight: 20 }} options={selectOptions2}>
</Select>
<span>表名称:</span>
<Select defaultValue="1" style={{ 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,虽然页面上确实少了一项,但是你发现第一项被复用了,给人感觉就是删除了最后一项。