【问题标题】:How to combine multiple API requests in one function with fetch() in React如何在一个函数中将多个 API 请求与 React 中的 fetch() 组合起来
【发布时间】:2021-07-08 10:47:06
【问题描述】:

我必须使用 getDataOnegetDataTwo。如何使用fetch()useStateuseEffect 将以下组合成一个函数?

const MyComponent = () => {
  const [loading, setLoading] = useState(false);
  const [dataOne, setDataOne] = useState<Data[]>([]);
  const [dataTwo, setDataTwo] = useState<Data[]>([]);

  const getDataOne = async () => {
    setLoading(true);
    const result = await fetch(
      "https://my-api-link-one"
    );
    const jsonResult = await result.json();

    setLoading(false);
    setDataOne(jsonResult);
  };

  const getDataTwo = async () => {
    setLoading(true);
    const result = await fetch(
      "https://my-api-link-two"
    );
    const jsonResult = await result.json();

    setLoading(false);
    setDataTwo(jsonResult);
  };

  useEffect(() => {
    getDataOne();
    getDataTwo();
  }, []);

更新:

我使用Promise.all设置它

const [loading, setLoading] = useState(false);
   const [dataOne, setDataOne] = useState<DataOne[]>([]);
   const [dataTwo, setDataTwo] = useState<DataTwo[]>([]);
   const [data, setData] = useState<DataOne[] & DataTwo>([]);

    const urls = [
        "https://url-one", "https://url-two",
      ];
    
      const getData = async () => {
        setLoading(true);
        const results = await Promise.all(
          urls.map((url) => fetch(url).then((res) => res.json()))
        );
    
        setLoading(false);
        setData(results);
        console.log(data);
      };

这还没有完全奏效。我现在如何正确使用useState(并处理来自 url 的两个数据)?最后我想要一个data 变量,这样我就可以映射这个变量:

{data.map((item) => {
          return (
// etc

【问题讨论】:

    标签: reactjs request fetch use-effect use-state


    【解决方案1】:

    您可以使用Promise.all。在此处阅读更多信息https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

    const getData = () => {
    setLoading(true);
    Promise.all([fetch('api-1'), fetch('api-2')]).then(results => {
     setDataOne(results[0]);
     setDataTwo(results[1]);
    }).finally(() => setLoading(false));
    }
    

    【讨论】:

    • 谢谢,我很接近了。我更新了我的问题。您知道如何以干净的方式实现这一目标吗?
    【解决方案2】:

    所以,Promise.all() 接受一个承诺数组,所以自然Promise.all() 只返回一个数组。因此,即使您的 results 变量仍然是一个数组,我还是建议对其进行解构,因为在这种情况下,只涉及两个 API 提取。查看您的更新,我认为只剩下一些小的修改,如下所示:

        const urls = ["https://url-one", "https://url-two",];
    
        const getData = async () => {
          setLoading(true);
          const [result1, result2] = await Promise.all(
            urls.map((url) => fetch(url).then((res) => res.json()))
         );
          setLoading(false);
          setDataOne(result1);
          setDataTwo(result2);
          console.log(data);
        };
    

    【讨论】:

    • 谢谢,但我的最后一个问题是在这种情况下如何使用useState?在我更新的答案中,我现在声明了 3 个 useState 变量。也许那是错误的。最后我希望它们合二为一 [data, setData],所以我可以map() data like {data.map((item) =&gt; {}
    • @meez 如果您期望来自 API 结果的数组,您可以将它们连接起来,对吗?我的意思是这样的事情应该可以setData([...result1, ...result2])
    • 您确定以数组形式获得响应吗?如果是,那么请您发送第二个 URL 的 JSON
    • 所以在 Promise 操作之后做这样的事情const modifiedResults2 = result2.myItems; 然后像这样组合setData([...result1,...modifiedResults2])。顺便说一句 results1 JSON 像 result2 还是不同?
    • 好的,谢谢,差不多了。现在我得到一个空数组,因为我认为我设置的类型不正确:const [data, setData] = useState&lt;TypeOne[] | TypeTwo[]&gt;([]);。映射项应包含 TypeOne 和/或 TypeTwo(results1 和 results2)
    【解决方案3】:

    利用.flat()Promise.all() 返回的数据数组重新格式化为保存响应obj/数组的状态,

    Promise.all(
        urls.map(url => 
            fetch(url).then(e => e.json())
        )
    ).then(data => {
        finalResultState = data.flat();
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      • 1970-01-01
      相关资源
      最近更新 更多