使用获取结果来发出另一个获取请求(JS / React)

时间:2018-10-18 01:04:46

标签: javascript reactjs fetch

使用一个获取请求的结果向另一个端点发出另一个获取请求的最佳方法是什么?如何确认第一次获取已完成且setState已发生?

class ProductAvailability extends React.Component {
  state = {
    store_ids: []
  }
  componentDidMount() {
    fetch(`myapi.com/availability?productid=12345`)
    .then((results) => {
      return results.json();
    })
    .then((data) => {      
      const store_ids = data.result.map((store) => {
        return store.store_id
      })
      this.setState({store_ids: store_ids})
    })

    /* At this point I would like to make another request
       to myapi.com/storedata endpoint to obtain information 
       on each store in the state.store_ids, and add details 
       to the state */
  }


  render() {
    return (
      <div>
        <p>STORE INFO FROM STATE GOES HERE</p>
      </div>
    )
  }
}

2 个答案:

答案 0 :(得分:1)

当您执行setState时,它将更新组件,因此,如果您已经阅读了文档,则在完成setstate之后自然要读取状态是在componentDidUpdate(prevProps,prevState)中。 我将您留给文档:https://reactjs.org/docs/react-component.html#componentdidupdate 注意:不要使用willupdate,因为在文档中阅读它是不安全的。

可以做进一步的考虑。如果可以避免将这些数据置于状态,则还可以在componendDidMount中进行所有操作(可能对所有其他请求使用promiseall),然后使用新旧数据设置状态,这是可取的,因为更新了组件只有一次。

答案 1 :(得分:0)

使用async/await更容易(.then/.catch需要做更多的工作-而且,请参考Bluebird的Promise.each函数)。为了清楚起见,最好将其从componentDidMount移到其自己的类方法中。

请注意,如果每个产品都在执行此操作,则此二级查询应在后端处理。这样,您只需要发出一个 AJAX请求并检索一个响应中所需的所有内容。

componentDidMount = () => this.fetchData();


fetchData = async () => {
  try {
    const productRes = fetch(`myapi.com/availability?productid=12345`) // get product data
    const productData = await productRes.json(); // convert productRes to JSON

    const storeIDs = productData.map(({store_id}) => (store_id)); // map over productData JSON for "store_ids" and store them into storeIDs

    const storeData = [];
    await Promise.each(storeIDs, async id => { // loop over "store_ids" inside storeIDs
      try {
        const storeRes = await fetch(`myapi.com/store?id=${id}`); // fetch data by "id"
        const storeJSON = await storeRes.json(); // convert storeRes to JSON
        storeData.push(storeJSON); // push storeJSON into the storeData array, then loop back to the top until all ids have been fetched
      } catch(err) { console.error(err) }
    });

    this.setState({ productData, storeData }) // set both results to state
  } catch (err) {
    console.error(err);
  }
}