Home > Back-end >  Updating useEffect api call url with user inputs
Updating useEffect api call url with user inputs

Time:09-28

I'm working on a project, where I need to update a datachart with user inputted dates. I'm having trouble on how to update the url inside the useEffect hook. Here's my relevant code:

const finalUrl =`${apiUrl}id=${id}&timing=${time}&start=${finalStart}&end=${finalEnd}`;
    console.log(finalUrl);

useEffect(() => {
    
    axios
      .get<AxiosResponse>(finalUrl, {
        headers: {
          "Content-Type": "application/json"
        }
      })
      .then(response => {
        setData(response);
      })
      .catch(error => {
        console.log(error);
      });
  }, []);
  console.log(data); 

Everything looks good until i get to the axios call. I cannot get useEffect to use the updated url. Logging the response data just gives the same every time. All values inside "finalUrl" are coming from the user.

CodePudding user response:

I'm going to assume that apiUrl and id never change, but that all the other things you're using in the API URL are inputs from the user.

If so, you need to rebuild the URL in the useEffect callback, and make the callback dependent on those user inputs, like this:

useEffect(() => {
    const finalUrl =`${apiUrl}id=${id}&timing=${time}&start=${finalStart}&end=${finalEnd}`;
    axios
        .get<AxiosResponse>(finalUrl, {
            headers: {
                "Content-Type": "application/json"
            }
        })
        .then(response => {
            setData(response);
        })
        .catch(error => {
            console.log(error);
        });
}, [time, finalStart, finalEnd]);

The callback will be called again when time, finalStart, or finalEnd change.


Note that you also need to disregard or cancel previous requests when the dependencies change, even if the request hasn't been completed yet. I don't use axios but as I understand it has a "cancel/cancellation token" you can use for doing that. Here's what it would look like with fetch, which uses AbortController:

useEffect(() => {
    const finalUrl =`${apiUrl}id=${id}&timing=${time}&start=${finalStart}&end=${finalEnd}`;
    // Create the controller so we can cancel the request
    const controller = new AbortControlller();
    // Pass `signal` to fetch vvvvvvvvvvvvvvvvvvvvvvvvvvv
    fetch<DataType>(finalUrl, {signal: controller.signal})
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error ${response.status}`);
            }
            return response.json();
        })
        .then(setData)
        .catch(error => {
            console.log(error);
        });
    // Return a cleanup callback
    return () => {
        // Cancel the request since its response would be out of date
        controller.abrt();
    };
}, [time, finalStart, finalEnd]);
console.log(data); 
  • Related