【问题标题】:React set state error outside of componentDidMount在 componentDidMount 之外反应设置状态错误
【发布时间】:2020-07-15 11:47:07
【问题描述】:

当我尝试在我的 retrieveRoleMembers 函数中设置状态时收到错误 Unhandled Rejection (Error): Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops. 不知道如何修复它,感谢任何反馈!

class MainCard extends Component {
state = {
    userResponseData:[] ,
    roleResponseDataID:[] 


}

handleChange = (tab) => {

    window.alert(`Tab changed to: ${tab}`);
};

retrieveRoleMembers(){

    var i,j;
    for (i = 0; i < this.props.userRoleDataValue.length; i++) {
        if(this.props.userRoleDataValue[i].role_id === this.state.roleResponseDataID.id){
             for(j=0;j<this.state.userResponseData.length;j++){
                 if(this.props.userRoleDataValue[i].user_id === this.state.userResponseData[j].id)
                 {
                      this.setState({ // This is where the error is happening
                        outputRoleMembers: this.state.userResponseData[j],
                      })

                 }
             }

}}}
componentDidMount() {
        this.props.getComponentById(VIEW_ROLES, Roles, this.props.searchValue.value).then(() => {
            return this.setState({ 

                roleResponseDataID: this.props.roles.data,
                cardHandle: false,
            })
            
        });

        this.props.fetchComponent([IS_FETCHING_DBUSERS, FETCH_DBUSERS_SUCCESS], users)
        .then(() => {
            return this.setState({

                userResponseData: this.props.users.data,
            })
        });

}
render() {
    if (this.props.cardHandle) {
        return null
    }
    else {

        if (this.props.sendOptionSelected === 'Role') {
            this.retrieveRoleMembers()
            return (
                <Card mr={'0px'}>
                    <Tabs defaultActiveTab="Members" onChange={this.handleChange} >
                        {/* Group of tabs */}
                        <Tabs.Tab label="Members">Members</Tabs.Tab>
                        <Tabs.Tab label="Access">Access</Tabs.Tab>

                        {/* Tab panels */}
                        <Tabs.Panel label="Members">
                            <Table
                                data={Array.isArray(this.state.outputRoleMembers) ? this.state.outputRoleMembers : [this.state.outputRoleMembers]}
                                defaultPageSize={[this.state.outputRoleMembers].length}
                                columns={
                                    [

                                        {
                                            Header: 'Fisrt Name',
                                            accessor: 'first_name'
                                        },
                                        {
                                            Header: 'Last Name',
                                            accessor: 'last_name'
                                        }

                                    ]
                                }
                                sortable={false}
                                resizable={false}
                                showPagination={false}
                                onSortedChange={() => { }}
                            />
                        </Tabs.Panel>
                    </Tabs>
                </Card>
            )
        }
    }
}


const mapStateToProps = state => {
        return {
            roles: state.roles.item,
            users: state.users
        }
    }
    export default connect(mapStateToProps, { getComponentById,fetchComponent })(MainCard);

当我将retrieveRoleMembers 更改为这样时,我的代码可以工作,但是当我检查控制台日志时,我看到了一个无限循环/为VIEW_DBUSERS 渲染

retrieveRoleMembers(){
        var i;
        for (i = 0; i < this.props.userRoleDataValue.length; i++) {
            if(this.props.userRoleDataValue[i].role_id === this.state.roleResponseDataID.id){
                 this.props.getComponentById(VIEW_DBUSERS, users, this.props.userRoleDataValue[i].user_id).then(() => {
                    return this.setState({
                        outputRoleMembers: this.props.users.data,
                   })
                });

    }}}

【问题讨论】:

  • 你在哪里打电话给retrieveRoleMembers?为什么不在循环结束时更新状态,而不是在每次迭代中更新?
  • 也许你以错误的方式从 HTML 调用retrieveRoleMembers。
  • 我在我的渲染中调用retrieveRoleMembers 来填充一个表,我真的没有理由为什么我在循环中调用它,但我认为它比必须保存一个更直接数组然后将其分配给outputRoleMembers ...关于循环外分配的外观有什么建议吗?
  • 如果状态发生变化,每次都会调用渲染方法。所以你说你用渲染来称呼它。这意味着它将调用retrieveRoleMembers 方法并设置状态(当您在retrieveRoleMembers 中设置状态时)......并且由于状态已更新,因此它将重新渲染视图。重新渲染视图意味着再次调用渲染方法。所以它正在创建循环。不要在 render 中调用它,而是在 componentDidMount 或其他地方调用它。
  • @SurjeetBhadauriya 请看我添加的渲染方法

标签: reactjs setstate


【解决方案1】:

问题是你在渲染方法中调用函数。那sets the State 并再次调用渲染方法等等。所以它创建了一个循环。

因此你得到

未处理的拒绝(错误):超过最大更新深度

我通过创建async 函数将所有内容放入componentDidMount

    componentDidMount() {
      this.preFetchData(); 
    }
    
    preFetchData async () { // made this async function.. using await to make code sync 
       await this.props.getComponentById(VIEW_ROLES, Roles, this.props.searchValue.value);
       await this.props.fetchComponent([IS_FETCHING_DBUSERS, FETCH_DBUSERS_SUCCESS], users);
    
       this.setState({ roleResponseDataID: this.props.roles.data, cardHandle: false, userResponseData: this.props.users.data }, () => {
            this.retrieveRoleMembers(); // call your method here 
       });
     }

【讨论】:

  • 感谢您的帮助!
  • 总是很高兴..!!谢谢
猜你喜欢
  • 2016-06-21
  • 2017-01-18
  • 1970-01-01
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 2018-04-10
  • 1970-01-01
相关资源
最近更新 更多