在 Ajax 回调中设置状态抛出错误:警告:setState(...):只能更新已安装或正在安装

IT技术 ajax reactjs
2021-05-20 01:25:39

我有一个相当简单的react容器组件,它尝试在从 componentDidMount 调用的 ajax 回调中调用设置状态。完整的错误是:

警告:setState(...):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了 setState()。这是一个无操作。请检查 UserListContainer 组件的代码。

我的 console.log 中的操作顺序是:

render
child-render
componentDidMount
ajax-data
[Big ol Error Message]

我开始使用 async/await,但是当我收到错误时,我返回到具有相同结果的回调。这是相关代码:

    export class UserListContainer extends React.Component<any, any>
{

    constructor() {
        super();
        this.state = {
            users: [], request: {}
        };

    }
    //componentDidMount = async () => {
componentWillMount = () => {
        console.log('componentWillMount');
        //var response: Models.IUserQueryResponse = await Api.UserList.get(this.state.request);
        Api.UserList.get(this.state.request).then((response) => {
            console.log('ajax-data');
            if (response.isOk) {
                this.setState({ users: response.data, request: response.state });
            }
        });
    }
    render() {
        console.log('render');
        return <UserList
            request={this.state.request}
            users={this.state.users}
            onEditClick={this.edit}
            onRefresh={this.refresh}
        />;
    }

任何帮助,将不胜感激。

2个回答

您不能在 componentWillMount 中设置状态,因为您的组件可能处于过渡状态......它也不会触发重新渲染使用 componentWillReceiveProps 或 componentDidUpdate。

现在抛开您的问题是您正在从 API 请求的回调中调用 setState。问题在于您可能已经卸载了该组件并且不想再设置 setState。

你可以用一个简单的标志来解决这个问题

constructor() {
    super();
    this.state = {
        users: [], request: {}
    };
    this.isMounted = false;
}
componentDidMount(){
    this.isMounted = true
}
componentWillUnmount(){
    this.isMounted = false;
}

然后在您的 api 请求中,您将执行此操作。

Api.UserList.get(this.state.request).then((response) => {
    console.log('ajax-data');
    if (response.isOk && this.isMounted) {
        this.setState({ users: response.data, request: response.state });
    }
});

我认为最好使用componentWillMount()而不是componentDidMount()因为您想要加载列表然后设置状态,而不是在安装组件之后。