在获取数据之前完成渲染组件

时间:2019-08-17 21:59:11

标签: javascript react-native fetch state

我正在尝试通过创建函数来获取数据。在该函数中,我正在尝试设置状态,并从componentDidMount方法调用它,但是遇到一些问题:

  1. 我不确定while是否是个好习惯,因为我正在循环和更改端点,以便每次都能获取新数据。
  2. 我试图从获取函数返回数据并在setState中使用componentDidMount,但是我怀疑有一个问题,因为componentDidMount在获取完成之前正在运行
  3. 我尝试使用Promise在数据上使用res.json(),但是我收到一个错误,指出res.json不是函数。
state = {
    title: [],
    image: [],
    rating: [],
  };

getData =  () => {
    let i = 1;
    while (i <= 9) {
       axios.get(`http://api.tvmaze.com/shows/${i}`)
      .then(response => console.log(response))
      .then(response => this.setState({
        title:response.data.data.name[i],
      }))
      .catch(error => console.log(error));
      i++;
    }
  };
  componentDidMount() {
    this.getData();
    console.log(this.state.title);
  }

2 个答案:

答案 0 :(得分:0)

您设置状态的方式将导致api中的最后数据被保存为状态,并且仅呈现最后一次调用

这样做

getData =  () => {
let i = 1;
while (i <= 9) {
   axios.get(`http://api.tvmaze.com/shows/${i}`)
  .then(response =>{
let prevState=this.state.title
prevState.push(response.data.data.name[i])
   this.setState({
    title:prevState,
  })})
  .catch(error => console.log(error));
  i++;
}

};

答案 1 :(得分:0)

如果您的目标是在获取信息后呈现JSX,那么建议您在stateisLoading中创建一个附加项,以便您进行设置到truefalse并有条件地渲染JSX

根据您在下面提供的示例,它看起来像以下内容:

class Shows extends React.Component {
  state = { 
    title: [], 
    image: [],
    rating: [],
    isLoading: true
  }

  componentDidMount() {
    this.getData()
  }

  getData = () => {
    // I've created a URL for each request
    const requestUrls = Array.from({ length: 9 })
      .map((_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`);

    const handleResponse = (data) => {
      // `data` is an array of all shows that you've requested

      // extract information about each show from the payload
      const shows = data.map(show => show.data)

      // handle shows data however you need it
      // and don't forget to set `isLoading` state to `false`
      this.setState({
        isLoading: false,
        title: shows.map(show => show.name),
        image: shows.map(show => show.url),
        rating: shows.map(show => show.rating.average),
      })
    }
    const handleError = (error) => {
      // handle errors appropriately
      // and don't forget to set `isLoading` to `false`
      this.setState({
        isLoading: false
      })
    }

    // use `Promise.all()` to trigger all API requests
    // and resolve when all requests are completed
    Promise.all(
      requestUrls.map(url => axios.get(url))
    )
      .then(handleResponse)
      .catch(handleError)
  }

  render() {
    const { isLoading, title, image, rating } = this.state

    // prevent showing your `JSX` unless data has been fetched
    // ideally, show a loading spinner or something that will
    // tell users that things are happening; 
    // returning `null` won't render anything at all
    if (isLoading) {
      return null
    }
    return (
      <div>...</div>
    )
  }
}

这样,通过Promise.all,就可以轻松推断正在执行的所有这些呼叫。

除此之外,使用componentDidMount从API提取数据是正确的选择,但是我会远离while循环,并使用Promise.all您的请求和map来创建一个承诺(请求)数组,这些承诺可以传递给Promise.all并立即处理。

工作示例: