在 componentDidMount 内的回调中设置状态

IT技术 reactjs react-native
2021-05-27 02:22:11

我目前正在使用 React 16.3(React Native),写在这里,它表明我应该在 componentDidMount 而不是 componentWillMount 内发出任何异步请求,因为它很快就会被弃用。

不幸的是,当我试图在 componentDidMount 中获取数据时,我收到了一个无操作警告,将从我的 axios 请求返回的数据设置为我的状态。

这是一个片段-

export default class MyComponent extends Component {
    state = {
      myData: []
    }

    componentDidMount() {
      axios.get('api-endpoint')
      .then(res => this.setState({ myData: res.data })
    }
    render() { return <View>...</View> }
}

和警告——

Warning: Can only update a mounted or mounting component. 
This usually means you called setState, replaceState, or 
forceUpdate on an unmounted component. This is a no-op.

Please check the code for the MyComponent component.
3个回答

这就是在你的组件中有异步代码的问题。例如,当 Promise 解决(可能需要几秒钟)时,用户可能已经导航到应用程序的另一部分,因此当 Promise 解决并尝试执行时setState- 您会收到尝试更新未安装组件的错误。

我的建议是使用诸如 redux-thunk、redux-saga 或 redux-observable 之类的东西作为你的异步逻辑......但是,你可以做一个简单的检查——但它是一个反模式

export default class MyComponent extends Component {
    state = {
      myData: []
    }

    componentDidMount() {
      this.isMounted = true;

      axios.get('api-endpoint')
      .then(res => {
        if(this.isMounted) {
          this.setState({ myData: res.data })
        }
      })
    }

    componentWillUnmount() {
      this.isMounted = false;
    }
    render() { return <div>...</div> }
}

我的建议是遵循适当的 Flux。您可以为您的MyComponentin附加商店侦听器,componentDidMount()如下所示。

componentDidMount() {
   //call async data fecthing method here
   store.addListener('eventname', onDataReceipt);
}

在此之前,您可以将状态更改逻辑移至onDataReceipt方法。调用异步数据提取componentDidMount()dispatch存储已注册到的操作。然后从商店发出事件。由于您已经订阅了 中的事件componentDidMount()onDataReceipt()因此将执行on 事件发射也不要忘记删除监听器componentWillUnMout()

componentWillUnMount() {
   store.removeListener('eventname', onDataReceipt);
}

Flux 会处理其余的你不必担心警告。

更新——我的组件被卸载的原因是因为我在我的父组件中设置状态。在父组件中设置状态时,它强制重新渲染组件,这会沿着树向下传递并在我的异步请求中间卸载。