4

I need to call 2 APIs for displaying data on my component but the second api needs headers from the response of first API. I am using React Hooks. I update the state from the first response so i can use it later for the second call, but it goes undefined. What am i doing wrong?

P.s a better way of doing this calls (maybe using async/await) would be much appriciated

 const [casesHeaderFields, setCasesHeaderFields] = useState([]);
 const [casesFields, setCasesFields] = useState([]);

  useEffect(() => {
    const fetchData = () => {
      const result1 = axios
        .get(`firstUrl`)
        .then(response => {
         //I need this as headers for my second API
          setCasesHeaderFields(
            response.data.result.fields
          );
        });

      const result2 = axios
        .get(`url${casesHeaderFields} //here i want to pass params from 
         //first response)
        .then(response => {
          setCasesFields(response.data.result.record_set);
        });
    };
    fetchData();
  }, []);
Besart Marku
  • 543
  • 1
  • 7
  • 14
  • chain your promises or use `async/await` and block execution of your `result2` call. what do you mean by `P.s a better way of doing this calls (maybe using async/await) would be much appriciated`? `async/ await ` is simple enough... – Adam Kosmala Aug 06 '19 at 12:44
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – jonrsharpe Aug 06 '19 at 12:59

5 Answers5

10

You can chain the results as they are regular promises: Ref

axios.get(...)
  .then((response) => {
    return axios.get(...); // using response.data
  })
  .then((response) => {
    console.log('Response', response);
  });
PEPEGA
  • 2,214
  • 20
  • 37
5

make the second call inside a .then chained to the end of the first promise chain ... in simple terms, chain your promises

Something like

useEffect(() => axios.get(`firstUrl`)
    .then(response => {
        setCasesHeaderFields(response.data.result.fields);
        return response.data.result.fields;
    })
    .then(casesHeaderFields => axios.get(`url${casesHeaderFields}`))
    .then(response => {
        setCasesFields(response.data.result.record_set);
    }), []);
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
3

The queries result1 and result2 look sequential but there are simultaneous. In other words, result2 doesn't wait for result1 to finish before being executed.

Here is a working example to chain promises using async/await:

useEffect(async () => {
  try {
    // Make a first request
    const result1 = await axios.get(`firstUrl`);
    setCasesHeaderFields(result1.data.result.fields);

    // Use resutlt in the second request
    const result2 = await axios.get(`url${"some params from result1"}`);
    setCasesFields(result2.data.result.record_set);
  } catch (e) {
    // Handle error here
  }
}, []);

EDIT

Based on comments, here is a best way to use async with useEffect without warning in the console:

useEffect(() => {
  const fetchData = async () => {
    try {
      // Make a first request
      const result1 = await axios.get(`firstUrl`);
      setCasesHeaderFields(result1.data.result.fields);

      // Use resutlt in the second request
      const result2 = await axios.get(`url${casesHeaderFields}`);
      setCasesFields(result2.data.result.record_set);
    } catch (e) {
      // Handle error here
    }
  };

  fetchData();
}, []);
Baboo
  • 4,008
  • 3
  • 18
  • 33
  • axios.get(`url${"some params from result1"}`)? for example like result1.data.fields? or i pass the state caseHeaderFields? – Besart Marku Aug 06 '19 at 13:06
1

You can write something like this:

  useEffect(() => {
      return axios
        .get(`firstUrl`)
        .then(response => {
          return response.data.result.field
        }).then(result => { 
         return axios.get(`url${result}`)
        });
   });

With async / await :

  useEffect(async () => {
      const result1 = await axios
        .get(`firstUrl`)
        .then(response => {
          return response.data.result.field
        });
      const result2 = await axios.get(`url${result1}`)
      return result2 
   });

1

You can use async/await to relieve the mess.

useEffect(async () => {
    const response = await axios.get(`firstUrl`)
    const result = await axios.get(`url${response.data.result.fields}`)
    console.log(result.data)
})
Abdulsamet Kurt
  • 1,090
  • 2
  • 10
  • 15