下面代码打印出来是空字符:这难道不是会更新的么:用的是蚂蚁的组件
import { Api_Module_Edit_Prepare, Api_Module_Edit_Save } from "../Request/Module"
import { Input, Card, Form, Row, Col, Space, Collapse, Button, message } from 'antd';
import { useNavigate, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import "../Css/Edit.sass"
export function Component() {
const navigate = useNavigate();
const { module = "", id = 0 } = useParams();
const [primary] = Form.useForm();
const [messageApi, contextHolder] = message.useMessage();
const [tableActive, setTableActive] = useState<string>(``)
const [tableData, setTableData] = useState<Record<string, React.ReactNode>>({})
const [tabList, setTabList] = useState([]);
const onFinish = (data: any) => {
const params = { table: tableActive, data: data }
Api_Module_Edit_Save(module, [params]).then((res) => {
messageApi.success("保存成功")
})
}
// 渲染:表单【 主表 + 子表 】:Card
const formatTableData = (data: any) => data.reduce((loop: any, item: any, index: number) => ({
...loop,
[item.table_name]: index === 0 ? renderFormItem(item) : renderTableItem(item)
}), {});
// 渲染:标签【 主表 + 子表 】
const formatTableTabs = (data: any) => data.map((item: any) => ({
key: item.table_name,
tab: item.display_name,
}))
// 渲染:主表表单
const renderFormItem = (table: any) => {
const renderFormItem = (columns: any) => columns.map((column: any) => (
<Col span={6} key={column.id}>
<Form.Item label={column.display_name} name={column.attr_name}>
<Input maxLength={100} placeholder={`请输入`} disabled={column.build_in == 1} />
</Form.Item>
</Col>
))
return (
<Form form={primary} name="project" onFinish={onFinish}>
{table.sections.map((section: any) => (
<Collapse
key={section.id}
defaultActiveKey={['1']}
items={[{
key: section.id,
label: section.display_name,
children: <Row gutter={[16 ,16]} key={section.id}>{renderFormItem(section.columns)}</Row>
}]} />
))}
</Form>
)
}
// 渲染:子表数据
const renderTableItem = (data: any) => data.map((item: any) => ({
}))
// 渲染:公共操作
const renderPublicActions = [
<Space>
<Button type={`dashed`} onClick={() => navigate(-1)}>返回</Button>
<Button type={`primary`} onClick={() => primary.submit()}>保存</Button>
</Space>
]
useEffect(() => {
Api_Module_Edit_Prepare(module).then((res) => {
setTableData(formatTableData(res.form))
setTabList(formatTableTabs(res.form))
setTableActive(res.form[0].table_name)
})
}, [module])
return (
<div className={`edit`}>
<Row gutter={[16, 16]}>
{contextHolder}
<Col span={24}>
<Card
actions={renderPublicActions}
tabList={tabList}
activeTabKey={tableActive}
tabProps={{ size: 'middle' }}
bodyStyle={{ padding: "15px"}}>
{tableData[tableActive]}
</Card>
</Col>
</Row>
</div>
)
}
Component.displayName = "Edit";
}, [module])
这里的设计存在一定的问题
onFinish
依赖了tableActive
onFinish
又是在setTableData(formatTableData(res.form))
中被引用的useEffect
的时候,tableActive
肯定是初始值,当请求完成更新tableActive
后,并不会触发setTableData(formatTableData(res.form))
这条逻辑重新执行,所以导致产生了一个过期闭包,onFinish
始终引用的是初次的tableActive
tableActive
其实也应该是这个useEffect
的依赖项但注意,加上之后,
tableActive
变化,这个useEffect
又会重新执行,会多请求一次,如果tableActive
又存在变化的话会导致死循环,所以这块需要考虑下设计是否合理