【问题标题】:Fetching data on component did mount with async await doesnt wait获取组件上的数据确实使用异步等待不等待
【发布时间】:2025-12-19 09:10:15
【问题描述】:

我试图在 componentDidMount 上获取一些数据来设置反应状态。

我在 componentdidMount 上使用异步等待,获取一些数据,等待它,当它完成后将我的状态设置为数据。

我在本文中遵循完全相同的模式:https://medium.com/front-end-weekly/async-await-with-react-lifecycle-methods-802e7760d802

这是我的 componentDidMount 方法:

  const url = "http://localhost:3001";
  const opts = {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query })
  };
  await fetch(url, opts)
    .then(res => res.json())
    .then(data => this.setState({
      photographers: data
    }))
    .catch(console.error);
}

然后在我的渲染方法中,我尝试使用状态值.. 但它未定义:

render() {

console.log('here:', this.state)

return (
  <React.Fragment>
    <div className="red ba">Hella!</div>
    <List photographers={this.state.photographers}/>
  </React.Fragment>
  )
}

我之前用过 asunc await 很多次,我知道它是如何工作的,但是为什么这不起作用?谢谢!

【问题讨论】:

  • 您不需要在componentDidMount 的示例代码中使用await,因为您从不在方法本身中使用结果。在组件实际安装到 DOM 后,componentDidMount 也会触发。所以,第一个render 已经发生了。而第一次渲染显然会在获取任何内容之前看到初始状态。

标签: reactjs asynchronous


【解决方案1】:

您应该删除 .then() .catch() 方法,它们正在返回承诺,而不是您应该使 componentDidMount 异步fetch await

constructor(props) {
    super(props)
    this.state = {
      photographers: []
    }
  }

async componentDidMount() {
  const url = "http://localhost:3001";
  const opts = {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query })
  };
  try {
    const response = await fetch(url, opts)
    if (!response.ok) {
      throw Error(response.statusText);
    }
    const json = await response.json();
    console.log(json)
    this.setState({ photographers: json });
  } catch(error) {
    console.log(error)
  }
}

你也可以用 try 和 catch 包围 fetch,这样你就可以处理 catch 块内的错误,或者如果 response.ok 不正确

【讨论】:

  • 我尝试了你的解决方案,但是当我尝试 console.log 时仍然使用我的渲染方法,状态为 null @onuriltan
  • 你能在 this.setState 之前 console.log json 对象吗?我猜你的查询对象不见了,它是从哪里来的?
  • 不,我无法在 componentdidMount 中记录任何内容,但在构造函数中是的.. 我的查询位于文件顶部并且它是正确的。 @onuriltan
  • 是的,错误是它试图从状态中读取摄影师.. 但它的 null... 因为它应该设置在组件上,但在获取 @onuriltan 后确实安装了
【解决方案2】:

这就是异步 javascript 的工作原理,代码将运行完成,这意味着,当您运行网络请求并在 componentDidMount 中写入 await 时,下一个代码不会停止并等待,一切都会照常进行(并且当网络请求完成后,then 代码中的代码将被执行),注意 await 只是一种更简单的编写 then 块的方式(实际上没有等待)

因为你不能用await停止渲染,所以你应该在数据不存在时处理,通常显示加载屏幕,你可以这样做:

// You should initialise the photographers in the state to be null
render() {

console.log('here:', this.state)

return this.state.photographers !== null ? (
  <React.Fragment>
    <div className="red ba">Hella!</div>
    <List photographers={this.state.photographers}/>
  </React.Fragment>
  ) : (<div>Loading...</div>)
}

【讨论】:

    【解决方案3】:

    您正在尝试结合异步调用的两种语法 - async/await 和 .then().catch() 只要坚持一个。

    我个人更喜欢将我的异步代码放在不同的函数中,并在 componentDidMount() 中使用它

    const fetchPhotographers = () => {  
      const url = "http://localhost:3001";
      const opts = {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ query })
      };
      fetch(url, opts)
        .then(res => res.json())
        .then(data => this.setState({
          photographers: data
        }))
        .catch(console.error);
    }
    
    componentDidMount() {
     fetchPhotographers()
    }
    

    【讨论】:

    • 如果这不起作用,那么您的代码中的其他部分一定有问题。所以,在这里添加整个组件的代码。