【问题标题】:React Component's render method called twice even after data fetched即使在获取数据后,React 组件的渲染方法也会被调用两次
【发布时间】:2019-02-01 06:26:26
【问题描述】:

ListFolders 是一个 React 组件。并且“文件夹”数据道具从 MainLayout 组件传递到此组件。

MainLayout 组件使用 redux connect 并获取“文件夹”。

这里,我在ListFolders里面的问题,在列出文件夹的时候有一些映射和计算。因此,因为第二次调用需要更多时间,这是一个重要的性能问题。

下面的基本示例。我正在使用redux-sagaimmutable.js。 我收到了name (ContainerDesc)id (IdEncrypted)haveChildFolderschildFolders

这里,它进入if (folders !== undefined) { ...代码块内部两次。

render() {
    const { classes, folders } = this.props;

    let reactListItems = [];
    if (folders !== undefined) {

        var iterator1 = folders[Symbol.iterator]();

        for (let item of iterator1) {

            reactListItems.push({ 
                'name': item.get('ContainerDesc'), 
                'id': item.get('IdEncrypted'),
                'haveChildFolders' : item.get('ChildContainers').size > 0,
                'childFolders': item.get('ChildContainers')
            })

        }
    }

    return (
        <List classes={{ root: classes.list, }}>
            ...
        </List>
    );
}

【问题讨论】:

    标签: javascript reactjs redux redux-saga immutable.js


    【解决方案1】:

    对于第二次调用,文件夹数据可能没有更改,也可能没有未定义,因此在 componentWillReceiveProps() 中添加一个检查文件夹数据是否已更改的条件,例如:

    componentWillReceiveProps(nextProps){    
         if (folders.length !== nextProps.folders.length) {
           return ...
        }
    }
    

    或者您可以添加条件 shouldComponentUpdate() 并在不满足条件时停止组件以进行更新

    shouldComponentUpdate(nextProps){    
             if (folders.length !== nextProps.folders.length) {
               return true
            }
            else{
              return false
            }
        }
    

    【讨论】:

    • 我用 shouldComponentUpdate 发现了一个新东西。在文件夹已经被写入并写入 this.props.folder 之后,它重新进入渲染方法,并且 this.props.folders 再次未定义。
    • 检查 nextProps.folders 的值,它可能包含所需的文件夹数据,因此将其存储在 state 或任何变量中并在 render 方法中使用
    【解决方案2】:

    我找到了两次调用ListFolders 的原因。 我在SidebarComponentSidebar 中使用ListFolders,我将material-ui hidden 用于桌面和移动菜单的助手。示例代码如下。

    <Hidden mdUp implementation="css">
       ...
       <Drawer variant="temporary" ... /* Sidebar Drawer */
    </Hidden>
    
    <Hidden smDown implementation="css">
       ...
       <Drawer variant="temporary" ... /* Sidebar Drawer */
    </Hidden>
    

    因为ListFolders 会多次渲染,甚至获取数据。 我认为我将使用纯 CSS 处理移动菜单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-16
      • 2020-02-18
      • 2019-03-05
      • 2022-01-19
      • 2020-07-23
      • 1970-01-01
      相关资源
      最近更新 更多