问题描述
Antd3.7.2中(好像后续版本,截止目前3.8.0也是)的Tree组件的expandedKeys属性设置了对应要展开的节点String[]数组,绘制树时,依据expandedKeys设置的节点确实是依次展开,但是发现:
1.若节点本身存在children,展开的这个节点不触发loadData方法,这样会让一些已存在children的节点无法异步加载数据。我之前用3.6.4版本时,每次展开节点均会触发loadData,而自己使用if(treeNode.props.children){}或者添加节点变量if(treeNode.props.refData.isLoad)这种方式来控制是否真正执行loadData(){}中的逻辑。
2.当expandedKeys:[]的expandedKeys.length>1时,比方说expandedKeys.length=3,当展开第二个之后的节点,会把之前loadData的节点再loadData一遍。就会出现unique-key的问题。
问题出现的环境背景及自己尝试过哪些方法
我的webpack配置是^3.0.0,即大版本不变,cnpm i后会自动更新下小版本。
一开始一直不知道为什么会这样,因为Tree组件我之前使用过这个属性。发现自动升级后第一感觉是这种使用方式是不是已经不被提倡,但是就细想一下,官网的教程没变,而且属性的功能确实是没达到效果,我确信这个是BUG。
解决办法是直接设置antd版本为3.6.4
相关代码
//请把代码文本粘贴到下方(请勿用图片代替代码)
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;
class Demo extends Component {
state = {
treeData: [
{
title: 'Expand to load00', key: '0',
// children: [
// { title: '00-0', key: '00-0' },
// { title: '00-1', key: '00-1' },
// { title: '00-2', key: '00-2' },
// ]
},
{ title: 'Expand to load01', key: '1' },
{ title: 'Expand to load02', key: '2' },
{ title: 'Expand to load03', key: '3' },
{ title: 'Tree Node04', key: '4', isLeaf: true },
{ title: 'Tree Node05', key: '5', isLeaf: true },
],
}
onLoadData = (treeNode) => {
console.log('loadData异步加载。。。。', treeNode);
return new Promise((resolve) => {
if (treeNode.props.children) {
resolve();
return;
}
setTimeout(() => {
treeNode.props.dataRef.children = [
{
title: 'Child Node1',
key: `${treeNode.props.eventKey}-0`
},
{ title: 'Child Node2', key: `${treeNode.props.eventKey}-1` },
{ title: 'Child Node3', key: `${treeNode.props.eventKey}-2` },
{ title: 'Child Node4', key: `${treeNode.props.eventKey}-3` },
];
this.setState({
treeData: [...this.state.treeData],
});
resolve();
}, 1000);
});
}
renderTreeNodes = (data) => {
return data.map((item) => {
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{this.renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode {...item} dataRef={item} />;
});
}
render() {
return (
<Tree
loadData={this.onLoadData}
expandedKeys={['0', '1', '2']}
>
{this.renderTreeNodes(this.state.treeData)}
</Tree>
);
}
}
ReactDOM.render(<Demo />, document.getElementById('root'));
你期待的结果是什么?实际看到的错误信息又是什么?
我代码中设置的是 expandedKeys={['0', '1', '2']},按理说loadData被调用3次(后面我用3.6.4版是只调用3次),但是loadData被调用了6次,因为我代码中的key是不重复的,如重复,到第4次就会报unique-key的错误。如下图(图中的key红字写错,以代码为准,有点仓促^_^):
修改一下代码,设置expandedKeys={['0']},并且 treeData数组第一项'Expand to load00'下的children注释放开,即这个节点已存在children节点了,代码如下:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;
class Demo extends Component {
state = {
treeData: [
{
title: 'Expand to load00', key: '0',
children: [
{ title: '00-0', key: '00-0' },
{ title: '00-1', key: '00-1' },
{ title: '00-2', key: '00-2' },
]
},
{ title: 'Expand to load01', key: '1' },
{ title: 'Expand to load02', key: '2' },
{ title: 'Expand to load03', key: '3' },
{ title: 'Tree Node04', key: '4', isLeaf: true },
{ title: 'Tree Node05', key: '5', isLeaf: true },
],
}
onLoadData = (treeNode) => {
console.log('loadData异步加载。。。。', treeNode);
return new Promise((resolve) => {
if (treeNode.props.children) {
resolve();
return;
}
setTimeout(() => {
treeNode.props.dataRef.children = [
{
title: 'Child Node1',
key: `${treeNode.props.eventKey}-0`
},
{ title: 'Child Node2', key: `${treeNode.props.eventKey}-1` },
{ title: 'Child Node3', key: `${treeNode.props.eventKey}-2` },
{ title: 'Child Node4', key: `${treeNode.props.eventKey}-3` },
];
this.setState({
treeData: [...this.state.treeData],
});
resolve();
}, 1000);
});
}
renderTreeNodes = (data) => {
return data.map((item) => {
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{this.renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode {...item} dataRef={item} />;
});
}
render() {
return (
<Tree
loadData={this.onLoadData}
expandedKeys={['0']}
>
{this.renderTreeNodes(this.state.treeData)}
</Tree>
);
}
}
ReactDOM.render(<Demo />, document.getElementById('root'));
得到的结果是第一项节点确实展开,但是这个节点的展开并没有调用loadData(后面我试了3.6.4版本的是可以的),如下图:
这就使得loadData实现代码中的
if (treeNode.props.children) {
resolve();
return;
}
显得没意义,而且我节点下有children你不能限制我loadData吧?我要刷新怎么弄?
后面怎么解决的