【问题标题】:Uncaught (in promise) TypeError: this.setState is not a functionUncaught (in promise) TypeError: this.setState is not a function
【发布时间】:2020-01-06 12:31:13
【问题描述】:

在我的父组件中,我从 json 文件加载数据并使用它来设置状态。使用 react-router,然后我将状态传递给子组件,该子组件在路由中呈现数据。此行为按预期工作。但是,当我尝试刷新路由时,父组件的状态(以及子组件的道具)会丢失,并且页面会抛出未定义的错误。

我尝试在子组件的ComponentDidMount生命周期方法中调用父组件的数据加载函数,但应用程序抛出错误Uncaught (in promise) TypeError: this.setState is not a function

父组件代码:

async loadWorldData() {
 await axios.get("../factbook.json")
    .then(res => {
      let Data = res && res.data.countries;
      Data = Object.values(Data).map(country => country.data) || [];
      let newData = this.removeNull(Object.values(Data));

      this.setState({ worldData: newData})
    });
}

子组件代码:

componentWillMount = () => {
  this.props.loadWorldData();
}

我不知道在不调用子生命周期方法中的父函数的情况下重新加载应用状态的另一种方法。

【问题讨论】:

  • 使用async await时不必使用promises
  • 你不能在componentWillMount中做setState。请将代码移至componentDidMount
  • 另外,您也不需要异步等待,因为您正在更新成功的状态,而且我认为没有必要阻止这样的渲染。如果你的渲染完全依赖于这个 API,那么要么在导航到这个屏幕之前获取它,要么显示一个加载器。

标签: reactjs async-await react-router state


【解决方案1】:

试试这个:这可能是一个绑定问题。

 loadWorldData = async() => {

 const res = await axios.get("../factbook.json")
 let data = res && res.data.countries;
 data = Object.values(Data).map(country => country.data) || [];
 let newData = this.removeNull(Object.values(Data));
 this.setState({ worldData: newData });

}

为什么这不起作用?

要使用 setState,您必须有权访问 this。普通函数绑定到this。有两种方法可以解决此问题:

首先:在构造函数中将函数绑定到this。

class App extends React.Component {
   constructor(props) {
      super(props);
      this.loadWorldData = this.loadWorldData.bind(this);
   }
}

二:胖箭头函数:

由于胖箭头函数绑定到this,您不必担心将它们绑定到constructor 中,如第一个示例所示。

【讨论】:

  • 啊,这行得通。我曾尝试做const loadWorldData = async() => ... ,但不允许使用 const。谢谢!
  • 如果这对您有帮助,请将答案标记为正确的答案:)
  • 不应该有任何绑定问题,因为 componentWillMount 被写成箭头函数。
  • @MilindAgrawal 你确定吗?
  • 是的,我对此非常肯定。我猜问题是 componentWillMount 内部的 setState 不会导致渲染。 reactjs.org/docs/react-component.html#unsafe_componentwillmount
【解决方案2】:
          async loadWorldData() {
           const self = this;
           await axios.get("../factbook.json")
            .then(res => {
               let Data = res && res.data.countries;
                 Data = Object.values(Data).map(country => country.data) || 
                                 [];
                  let newData = this.removeNull(Object.values(Data));

                  self.setState({ worldData: newData})
                 });
           }

你可以删除 async await 你不需要它们。

【讨论】: