How to combine multiple API requests in one function with fetch() in React

Viewed 6845

I have to functions getDataOne and getDataTwo. How do I combine below into one function, using fetch(), useState and useEffect?

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();
  }, []);

Update:

I set it up using 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);
      };

This is not totally working yet. How do I use useState now correctly (and handle both data from urls)? In the end I want to have one data variable so I can map over this variable:

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

So, Promise.all() accepts an array of promises, so naturally Promise.all() returns an array only. So even though your results variable still is an array I would recommend destructuring it because in this case there are only two API fetches involved. Looking at your update, I think there's only small modifications left which are as follows :

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

Utilize .flat() to reformat the data array returned from the Promise.all() into your state which holds the response obj/array,

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