2

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 3

2

You can use Promise.all. Read more here 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));
}
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, I am close.. I updated my question. Do you know how to achieve that in a clean way?
1

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

5 Comments

thanks, but my last question is how do I use useState in this case? In my updated answer I have now 3 useState variables declared. Maybe that's wrong. In the end I want them into one [data, setData], so I am able to map() data like {data.map((item) => {}
@meez if you're expecting arrays from both the API results you can concatenate them, right? I mean something like this should work setData([...result1, ...result2])
Are you sure you're getting response as an array? If yes then could you please send the JSON of 2nd URL
So after Promise operation do something like this const modifiedResults2 = result2.myItems; Then combine like this setData([...result1,...modifiedResults2]). By the way is results1 JSON like result2 or is it different?
Ok thanks, almost there. Now I get an empty array because I think I set my types not correct: const [data, setData] = useState<TypeOne[] | TypeTwo[]>([]);. The mapped items should contain TypeOne and or TypeTwo (results1 and results2)
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.