Antd3.7.2中Tree的expandedKeys属性设置,展开节点时,loadData方法错乱(3.6.*是可以的)?

新手上路,请多包涵

问题描述

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吧?我要刷新怎么弄?

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