Home > Back-end >  useEffect for chained fetch calls
useEffect for chained fetch calls

Time:07-09

I'm chaining two fetch calls to retrieve data. The first call gets a token and then second call uses that token to get the data. Here's an example:

fetch("[GET THE TOKEN]")
    .then((response) => response.json())
    .then(token => {
    fetch("[GET DATA]?token=" token)
      .then((response) => response.json())
      .then((data) => {
        return data;
      });
  })

The issue is that I need to make lots of different calls sometimes within the same component and writing that chained call over and over again can get tedious and if I need to make changes it's a lot of code to edit.

I came up with a functional solution but I haven't stress tested it yet. I'm still a react noob so feedback would be helpful

context.jsx

const [token,setToken] = useState('')
const fetchToken = async () => {
    fetch("[GET THE TOKEN]")
    .then(response => response.json())
    .then(data => {
      setToken(data);
    });  
}

component.jsx

const {token, fetchToken } = useContext(context)

//fetch data function
const [initFetch,setInitFetch] = useState(false);
const fetchData = () => {
 fetch("[GET DATA]?token=" token)
  .then((response) => response.json())
  .then((data) => {
    return data;
  });
}

//action that inits fetch data
const submitForm = () => {
  setInitFetch(true)
}

//useEffect that will trigger the function on initFetch and token const changing values
useEffect(() => {
  if (token && initFetch === true) {
    fetchData();
  }
},[token,initFetch]);

CodePudding user response:

I see that you want to call this fetch function when you submit the form, Therefore, you should not do that with an useEffect, simply because you don't need to.

Use the useCallback hook and create an async function inside of it. Call it almost wherever you want.

See:

const MyComponent = () => {

  const {token, fetchToken } = useContext(context)
  const [initFetch, setInitFetch] = useState(false);

  const fetchData = useCallback(async () => {
    const response1 = await fetch(`[GET DATA]?token=${token}`);
    const jsonFromResponse1 = await response1.json();

    return jsonFromResponse1;
  }, [token])

  const randomFunc = async () => {
    const data = await fetchData()
  }

  return (
    <button onClick={fetchData}>Button</button>
  )
}

The dependency array of useCallback is crucial, if you don't insert it, when the token changes, the hook will never update the function with its new value.

You can continue to use then. But I strongly recommend you to try await/async. It will make your code way easier and readable.

CodePudding user response:

What I get from you question, that you are looking for some way to not repeat your fetch calls. If that's so, I believe you can go with a custom hook that you can call every time you need. something like that

const useFetchFn=(arg)=>{
  fetch(arg)
  .then((response) => response.json())
  .then((data) => {
    return data;
  });
}

Then in your component

const [token,setToken] = useState('')
const fetchToken =useFetchFn("[GET THE TOKEN]")
  • Related