如何在异步调用中使用 React 中的 API?

IT技术 javascript api reactjs
2021-05-03 03:37:11

所以我试图用 React 弄脏我的手。我非常决心使用 ReactJS编写维基百科查看器项目。然而,在使用 React 组件从维基百科的 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 sying "Cannot read property 'wikiData' of null",之后数据从调用返回并且不再为 null,但这会导致渲染中断。 控制台消息 我确实尝试使用 componentDidMount 代替,但这也不起作用。我不知道该怎么做,我想了解这个过程。这是我的代码笔:https ://codepen.io/Banhawy/pen/eEmQBW ? editors = 1010

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

4个回答

我对您的代码进行了一些修改,并提出了一些意见,希望对您有所帮助。

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>
    )
  }

}

您说在服务响应任何响应之前调用渲染方法是对的。

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

你打错字了componentWillMount,你写的this.setStatethis.state我还建议您将此声明移至构造函数:

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

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

首先,您应该在类构造函数上拥有组件默认状态,因此将前三行移动到方法 componentWillMount 上。

其次,您的默认状态是错误的:

this.setState = {
    wikiData: undefined
}

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