7

I'm learning React (with hooks) and wanted to ask if every single API call we make has to be inside the useEffect hook?

In my test app I have a working pattern that goes like this: I set the state, then after a button click I run a function that sends a get request to my API and in the .then block appends the received data to the state.

I also have a useEffect hook that runs only when the said state changes (using a dependency array with the state value) and it sets ANOTHER piece of state using the new data in the previous state. That second piece of state is what my app renders in the render block.

This way my data fetching actually takes place in a function run on a button click and not in the useEffect itself. It seems to be working.

Is this a valid pattern? Thanks in advance!

Edit: example, this is the function run on the click of the button

const addClock = timezone => {
    let duplicate = false;
    selectedTimezones.forEach(item => {
      if (item.timezone === timezone) {
        alert("Timezone already selected");
        duplicate = true;
        return;
      }
    });
    if (duplicate) {
      return;
    }
    let currentURL = `http://worldtimeapi.org/api/timezone/${timezone}`;
    fetch(currentURL)
      .then(blob=>blob.json())
      .then(data => {
        setSelectedTimezones(prevState => [...prevState, data]);
      }
        );
  }

skyboyer
  • 22,209
  • 7
  • 57
  • 64
jjcreator
  • 73
  • 1
  • 5

2 Answers2

5

Yes, apis calls that happen on an action like button click will not be part of useEffect call. It will be part of your event handler function.

When you call useEffect, you’re telling React to run your “effect” function after flushing changes to the DOM

useEffect contains logic which we would like to run after React has updated the DOM. So, by default useEffect runs both after the first render and after every update.

Note: You should always write async logic inside useEffect if it is not invoked by an event handler function.

Jagrati
  • 11,474
  • 9
  • 35
  • 56
  • If useEffect by default runs on each render then why do we have to separately have them, why can't we do sideEffects in our render function? – Suraj Jain Jul 09 '22 at 03:31
2

Yes, you can make api requests in an event handler such as onClick.

What you don't want to do is make a request directly inside your functional component (since it will run on every render). As long as the request is inside another function and you only call that function when you actually want to make a request, there is no problem.

Paul
  • 139,544
  • 27
  • 275
  • 264
  • Do you mind elaborating on this a little? If you are calling the function that performs the api render in your onClick's event, then isn't that directly inside your functional component (in your functional component's return statement)? – timman Apr 17 '21 at 08:31
  • @timman `onClick={makeRequest()}` would be calling it directly during render (and not waiting for a click), and yes that would be bad. These are both fine though: `onClick={makeRequest}` and `onClick={() => makeRequest()}`. – Paul Apr 17 '21 at 11:36