react+antd项目,项目中使用异步加载树,点击树中的箭头加载数据。但是一点击就报错,报错如下
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;
});
这里少了一个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清理中的所有订阅和异步任务