react+antd项目,异步加载树加载数据后页面崩溃报错?怎么解决?

react+antd项目,项目中使用异步加载树,点击树中的箭头加载数据。但是一点击就报错,报错如下

img


项目代码如下



    function updateTreeData(list, key, children) {
        console.error('asdasdasdadsads', list, key, children);
        return list.map(node => {
            console.log(node, node.pcfid);
            if (node.cfid === key) {
                console.error('222222222', node);
                console.error('222222222', children);
                return { ...node, children };
            }
            if (node.children) {
                return { ...node, children: updateTreeData(node.children, key, children) };
            }
            console.error('111111111111111111111', node);
            return node;
        });
    }

export default () => {
const [treeList, setTreeList] = useState([]);
const [checkedKeys, setCheckedKeys] = useState([])

    function handleLevelChange(e) {
        console.log('e: ', e)
        getChildRelationList({
            fid: e,
        }).then(res => {
            if (res.code === '0') {
                setResult(res.data)
                const result = transferData1(res.data, '-1');
                setTreeList(result)
                console.log(result);
            }
        })
    }

    function transferData(list, fatherId) {
        // console.error('list, fatherId', list, fatherId);
        let arr = []

        list.forEach(item => {
            if (item.pcfid === fatherId) {
                arr.push({
                    title: item.title,
                    key: item.key,
                    children: transferData(list.filter(element => element.pcfid !== fatherId), item.cfid),
                    pcfid: item.pcfid,
                    cfid: item.cfid
                })
            }
        })

        return arr;
    }

    function transferData1(list, fatherId) {
        // console.error('list, fatherId', list, fatherId);
        let arr = []

        list.forEach(item => {
            if (item.pcfid === fatherId) {
                arr.push({
                    title: item.companyName,
                    key: item.levelFid,
                    children: [],
                    pcfid: item.pcfid,
                    cfid: item.cfid
                })
            }
        })

        return arr;
    }

    function onLoadTreeData(node) {
        console.error('------------', node);
        new Promise((resolve) => {
            // if (children) {
            //     resolve();
            //     return;
            // }
            getChildRelationList({ fid: node.key, pcfid: node.cfid }).then(res => {
                // console.log('--------------------', res);
                let arr = []

                res.data.forEach(item => {
                    if (item.pcfid === node.cfid) {
                        arr.push({
                            title: item.companyName,
                            key: item.levelFid,
                            children: [],
                            pcfid: item.pcfid,
                            cfid: item.cfid
                        })
                    }
                })
                if (res.code === '0') {
                    // const result = transferData(res.data, node.pcfid)
                    // console.error('00000', result);
                    // let conductList= [ ...treeList,...arr ]
                    // const result = transferData(conductList, '-1');
                    // setTreeList(...result)
                   //  console.error('222222222', result);
                   //  console.error('222222222', conductList);
                    setTreeList(origin =>
                         updateTreeData(origin, node.cfid, arr)
                     );
                     resolve();
                }
            })
        });
    }



    function onCheck(keys) {
        setCheckedKeys(keys)
    }

    return (
      
            <Modal
                visible={visible}
                footer={null}
                width={800}
                onCancel={() => { setVisible(false) }}
            >
                <Form
                    form={form}
                    onFinish={onFinish}
                    labelCol={{ span: 6 }}
                    wrapperCol={{ span: 14 }}
                >

                        <Tree treeData={treeList} loadData={onLoadTreeData} checkable checkStrictly defaultExpandAll={true} checkedKeys={checkedKeys} onCheck={onCheck} />

                </Form>
            </Modal>
        </div>
    )
}

这问题在哪里,要怎么解决?

此错误的原因一般是异步任务在组件销毁后仍然更新状态所致.
解决办法: 设置一个是否允许异步任务更新状态的标志变量, 异步任务更新状态前先判断此变量的值, 同时在组件中 使用useEffect 函数需返回一个清除函数来设置此标志.
因为你的描述和给出的代码不全, 无法给出具体的修改建议, 只能给出一个类似的示例:


useEffect(() => {
    let isUnmount = false;      
    const fetchDetail = async () => {
      const res = await getDetail(detailId);
      if (res.code === 0 && !isUnmount) {  //加上判断isUnmount才去更新数据渲染组件
        setDetail(res.data);
      }
    };
    fetchDetail();
    return () => isUnmount = true;   
  });


img

这里少了一个return 案例是用箭头函数 你扫return


return new Promise()

官方案例挺完整的,你可以先copy一下,慢慢改成你的数据
https://ant.design/components/tree-cn/#components-tree-demo-dynamic

import { Tree } from 'antd';
import { useState } from 'react';
const initTreeData = [
  {
    title: 'Expand to load',
    key: '0',
  },
  {
    title: 'Expand to load',
    key: '1',
  },
  {
    title: 'Tree Node',
    key: '2',
    isLeaf: true,
  },
]; // It's just a simple demo. You can use tree map to optimize update perf.

const updateTreeData = (list, key, children) =>
  list.map((node) => {
    if (node.key === key) {
      return { ...node, children };
    }

    if (node.children) {
      return { ...node, children: updateTreeData(node.children, key, children) };
    }

    return node;
  });

const App = () => {
  const [treeData, setTreeData] = useState(initTreeData);

  const onLoadData = ({ key, children }) =>
    new Promise((resolve) => {
      if (children) {
        resolve();
        return;
      }

      setTimeout(() => {
        setTreeData((origin) =>
          updateTreeData(origin, key, [
            {
              title: 'Child Node',
              key: `${key}-0`,
            },
            {
              title: 'Child Node',
              key: `${key}-1`,
            },
          ]),
        );
        resolve();
      }, 1000);
    });

  return <Tree loadData={onLoadData} treeData={treeData} />;
};

export default App;

无法对已卸载的组件执行反应状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。要修复,

取消useEffect清理中的所有订阅和异步任务