【问题标题】:Can't perform a React state update on an unmounted component?无法对未安装的组件执行 React 状态更新?
【发布时间】:2019-05-30 13:35:03
【问题描述】:

我正在 componentDidMount 中获取数据并更新状态,并且出现了著名的警告:

无法对未安装的组件执行 React 状态更新。这是 无操作,但它表明您的应用程序中存在内存泄漏。修理, 取消所有订阅和异步任务 componentWillUnmount 方法。

state = {
    post: null
}

render() {
    console.log(this.props.postId)
    if (this.props.post) {
        return (
            <div>
                <h3> {this.state.post.postTitle} </h3>
                <p> {this.state.post.postBody} </p>
            </div>

        );
    } else {
        return <Redirect to="/blog" />
    }
}
componentDidMount() {
    this._isMounted = true;
    axios
        .get('https://jsonplaceholder.typicode.com/posts/' + + this.props.postId)
        .then((response) => {
            let post = {
                id: response.data.id,
                postTitle: response.data.title,
                postBody: response.data.body
            }
            this.setState((prevState,props)=>{
                console.log('post',post)
                console.log('prevState',prevState)
                console.log('props',props)
            })
        })
        .catch((e) => {
            console.log('error', e)
        })
}

}

是什么导致了这个警告?获取数据和更新状态的最佳方法是什么?

【问题讨论】:

  • 组件可能会在通过axios 的 Ajax 请求完成之前再次卸载。

标签: reactjs


【解决方案1】:

您的问题与以下question相同。

组件是如何开发的,可以进入一个循环,无限执行render。为防止这种情况发生,请再添加一个状态和控件以仅发出 1 次请求或那些需要但“注意”的请求。

另外,您的代码需要进行一些更改,您可以使用 State 来验证是否显示某些内容,一旦发出请求,再次设置状态。通过一些更改,您的代码可能如下所示:

state = {
    loadingData: true,
    post: null
}

render() {
    if (!this.state.loadingData) {
        return (
            <div>
                <h3> {this.state.post.postTitle} </h3>
                <p> {this.state.post.postBody} </p>
            </div>
        );
    } else {
        return <Redirect to="/blog" />
    }
}
componentDidMount() {
    this._isMounted = true;
    if(this.state.loadingData)
        axios
            .get('https://jsonplaceholder.typicode.com/posts/' + + this.props.postId)
            .then((response) => {
                this.setState({
                    loadingData: false,
                    post: {
                        id: response.data.id,
                        postTitle: response.data.title,
                        postBody: response.data.body
                    }
                })
        })
        .catch((e) => {
            console.log('error', e)
        })
}

我希望它有用。 问候

【讨论】:

    【解决方案2】:

    只需在状态中创建标志:isMounted: false。在componentDidMount设置状态isMounted = true和在componentWillUnmount:设置状态isMounted = false

    并且在需​​要使用setState函数的异步函数中,用条件if(this.state.isMounted) { ....setState action }包装它们

    【讨论】:

      猜你喜欢
      • 2021-07-01
      • 2020-11-21
      • 2019-11-09
      • 2021-05-30
      相关资源
      最近更新 更多