【问题标题】:How to use APIs in React with Asynchronous calls?如何在 React 中通过异步调用使用 API?
【发布时间】:2018-01-01 22:12:41
【问题描述】:

所以我试图用 React 弄脏我的手。我非常决心使用 ReactJS 编写 wikipedia viewer 项目。然而,在使用 React 组件从 wikipedia 的 API 获取数据后,我昨天碰壁了。而且我认为这与异步调用有关。

我定义了一个接受查询并将其注入 API url 的常量: javascript const apiUrl = query => `https://crossorigin.me/https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=${query}` 然后我定义了一个在 ComponentDidMount 状态下异步获取 API 的类:

class Wiki extends React.Component {
constructor(props){
    super(props);
  console.log('Inside Constructor')
}
componentWillMount(){
  this.setState = {
    wikiData: undefined
  }
  console.log('Before fetch')
    fetch(apiUrl(this.props.query))
    .then(console.log('fetch successful'))
    .then(response => {
        if(!response.ok){
            throw Error("Response not ok")
        }
        return response
    })
    .then(data => data.json())
    .then(data => {
        this.setState ={
            wikiData: data
        }
      console.log(data)
    })

}
render(){
    if(!this.state.wikiData == null) return <p>No answer</p>
    else{
    return (
        <div>
            <h1>Something happened</h1>
        <h2>{this.state.wikiData[0]}</h2>
        </div>
    )
    }
}

}

当我在应用程序组件中调用它时,我收到一个 TypeError 提示“无法读取 null 的属性 'wikiData'”,之后数据从调用返回并且不再为 null,但这会导致渲染中断。 Console messaqges 我确实尝试使用 componentDidMount ,但这也不起作用。 我不知道该怎么做,我想了解这个过程。 这是我的代码笔: https://codepen.io/Banhawy/pen/eEmQBW?editors=1010

我想知道如何仅在对 API 的调用返回数据后渲染组件,以便在渲染之前访问和处理它。

【问题讨论】:

    标签: javascript api reactjs


    【解决方案1】:

    我已经稍微修改了您的代码,并制作了一些希望对您有所帮助的 cmets。

    class Wiki extends React.Component {
    
      constructor(props) {
        super(props);
    
        // this.state, not this.setState.
        // Also, it helps if you set your initial value to the value
        // to what you expect from your fetch (ie an array, albeit empty)
        this.state = { wikiData: [] }
      }
    
      // componentDidMount rather than componentWillMount
      // https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/
      componentDidMount() {
        fetch(apiUrl(this.props.query))
          .then(response => {
          .then(data => data.json())
          .then(data => this.setState = { wikiData: data }
          });
      }
    
      render() {
    
        // Check to see if your initial state is empty or not
        if (!this.state.wikiData.length) return <p>No answer</p>
    
        // No need for your else here. If your state is not empty, the first
        // return doesn't run, but this one does as a default.
        return (
          <div>
            <h1>Something happened </h1>
            <h2>{this.state.wikiData[0]}</h2>
          </div>
        )
      }
    
    }
    

    【讨论】:

    • 如果在api 解决时我移动到其他路径,因此该组件被卸载,会发生什么情况。 this.setState试图在未安装的组件上设置状态 失败。我该如何处理这些情况?
    • @guleria 您应该尽最大努力在componentWillUnmount 中取消这些请求。像 axios 这样的库支持请求取消。
    【解决方案2】:

    您说得对,即在服务响应任何响应之前调用了渲染方法。

    因此,当 wikiData 字段未定义时,您必须通过显示加载微调器等来调节渲染,并且当服务返回数据时,您将渲染 wikiData。

    【讨论】:

      【解决方案3】:

      您在componentWillMount 中打错字,您写的是this.setState 而不是this.state。我还建议您将此声明移至构造函数:

      class Wiki extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            wikiData: undefined
          }
        }
        ...
      }
      

      【讨论】:

        【解决方案4】:

        你的代码有一些错误,让我扩展一下。

        首先你应该在你的类构造函数中设置你的组件默认状态,所以在方法 componentWillMount 上移动你的前三行。

        第二,你的默认状态是错误的:

        this.setState = {
            wikiData: undefined
        }
        

        this.setState 是一个函数,要设置默认状态,您应该使用this.state

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-05
          • 2019-04-17
          • 2019-01-20
          • 1970-01-01
          • 2020-06-11
          • 2019-01-21
          • 2019-01-22
          • 2021-12-12
          相关资源
          最近更新 更多