React 的 Hooks 为什么获取不到最新值?

下面代码打印出来是空字符:这难道不是会更新的么:用的是蚂蚁的组件

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])
阅读 883
1 个回答

这里的设计存在一定的问题

  • onFinish 依赖了 tableActive
  • onFinish 又是在 setTableData(formatTableData(res.form)) 中被引用的
  • 首次进入这个 useEffect 的时候,tableActive 肯定是初始值,当请求完成更新 tableActive 后,并不会触发 setTableData(formatTableData(res.form)) 这条逻辑重新执行,所以导致产生了一个过期闭包,onFinish 始终引用的是初次的 tableActive
  • 因此这里 tableActive 其实也应该是这个 useEffect 的依赖项

但注意,加上之后,tableActive 变化,这个 useEffect 又会重新执行,会多请求一次,如果tableActive又存在变化的话会导致死循环,所以这块需要考虑下设计是否合理
image.png
image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏