2023-10-12
4824
#react
Sebastian Weber
28214
Oct 12, 2023 ⋅ 17 min read

A complete guide to the useEffect React Hook

Sebastian Weber Fell in love with CSS and JS over 20 years ago.

Recent posts:

Building a Full-Featured Laravel Admin Dashboard with Filament

Building a full-featured Laravel admin dashboard with Filament

Build scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.

Kayode Adeniyi
Dec 20, 2024 ⋅ 5 min read
Working With URLs In JavaScript

Working with URLs in JavaScript

Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.

Joe Attardi
Dec 19, 2024 ⋅ 6 min read
Lazy Loading Vs. Eager Loading

Lazy loading vs. Eager loading

In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.

Njong Emy
Dec 18, 2024 ⋅ 5 min read
Deno logo over an orange background

How to migrate your Node.js app to Deno 2.0

Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]

Yashodhan Joshi
Dec 17, 2024 ⋅ 7 min read
View all posts

22 Replies to "A complete guide to the useEffect React Hook"

  1. Great article! Thank you! A small feedback in “The cleanup function is called multiple times.”, I think you put in the wrong video 😉

  2. Great write up! One question I have is what are the benefits to using useEffect with the ‘gate’ ref and if checks for api calls that need to run only when a certain event happens like a button click? To me it seems harder to read and adding more complexity than just calling the api from the button click handler. I know that its ‘the react way’ but why is it better?

  3. Thanks Tdot. Regarding your question, using a “gate / boolean flag pattern” should only rarely be necessary. Most of the time, it points to problematic design. I also had to think long and hard to find an example for this article. In my everyday work, I almost never had to do something like this.
    This being said, in your described example you don’t need such a ref in combination with a button click. If I understand you right, you want to execute api calls whenever the user clicks a button – this falls into the normal pattern as I mentioned in the article “you should design your components to execute effects whenever a state changes, not just once”. If the user clicks your button, you update the state, a render happens, and then you can execute one or more effects depending on the changed state.

    If I have misunderstood you, would you have a concrete example?

    Regarding your statement that using this “gate pattern with refs” is more complicated – I am in complete agreement. Even with the small tracking example in this article, it is relatively complicated to execute a function only once when an event has occurred. You should avoid such an approach if possible (try to redesign your component) to have readable and understandable code.

  4. This code is part of a simplified custom fetch hook and just re-throws the error again. In a real world project, you would most likey have a more advanced error handling, e.g., have another error state and return it to the callee to present some kind of error message / view.

  5. Hello, I have a question about useEffect with functions in contexts. In your example you are using useCallback to avoid recreating the function but are creating a new object in the value of the provider. I have this confusion because of this https://reactjs.org/docs/context.html#caveats. So is it ok to do it like in your example or will it cause unintentional re-renders like in the example of the react docs? Thanks

  6. Hello Alejandro, that’s a really good question! Yes, you’re right, there is a new object created with the following inline code value={{ onDarkModeChange }} which might lead to more re-renders of the IntervalComponent as necessary. So as you suggested with the react docu link, we could try to extract this object (maybe with useMemo?). I need to check this. However, my goal during the time of writing the article to make sure that the useEffect in the Counter component will not be invoked because of the re-creation of the onDarkModeChange function. Because we used useCallback in the EffectsDemoContext component and we do only use the same function reference all the time because of destructuring, the useEffect dependency is “stable”:
    const { onDarkModeChange } = useContext(EffectsContext);

    I hope this was helpful for you!

  7. This is a very good, and necessary article on useEffect, thank you for writing it.

    I have to say, though, that the direction React is going scares me to death. One of the best things about React when I started using it 5 years ago is that it was easy to read and understand what was going on. This is patently false now. Take an experienced Javascript developer who has been using any other client-side tool for 5+ years, even non-hooks React, and show them the examples in this article. They will have absolutely no idea what is going on. How could they possibly understand what a function (useEffect) that takes a function and returns a function, with an optional data array does? The very fact that eslint has to have a god-level plugin to handle a dependency array should tell the developers that they have gone way, way off track.

    The same example using objects might be complicated as well, but with well-named functions like componentDidMount it can be figured out without a deep dive into the docs and an article like this one. (This is a big deal when hiring new developers that have to go in and make minor changes to existing code.) Now take a code base of a couple hundred thousand lines, and you can see how much of a problem this becomes.

    I understand the argument for hooks. I understand that it is better for solving some specific problems, and is great for small, uncomplicated projects. It is a nice *optional* addition. Yet having written some very complicated front ends, I can’t imagine creating a new project with React Hooks. I just hope the React devs never get rid of the object-based interface, or a mountain of rewriting is going to cripple a lot of companies for years.

    Again, thanks for writing this, as we have no choice but to follow the React team’s lead, and the React docs are fairly trivial with their examples. This is much, much better. I have recently started writing all new code in Hooks, and am starting to hit all of the issues in this article (even for a relatively simple component).

    1. Thank you very much John. I really appreciate your kind words.

      In addition, I have the same thoughts like you. I have very good devs in my team but they do struggle sometimes with hooks and sometimes don’t even know because they don’t know some related concepts. You have to investigate and practice heavily to master hooks/React.
      We had for many weeks wrong usage of hooks because we had a wrong configuration regarding the eslint hook plugin. The consequences were we built the app around wrong/missing dependencies. After turning on the eslint plugin it was not easy to add the right deps and fix the app again.
      As you said the class based approach was more explicit and many devs had less problems.

      I hope React gets easier again. There are some new frameworks that seems to be easier.

  8. Hi! I forgot to mention here my thanks! This is a really great article, I follow up everything here with exercises and it really helps me a lot to understand and every day as a good practice for my React Project.
    I congratulate you for this great job! Thanks again!

  9. Do you have any guidelines for dependencies that use array values? they seem to suffer to similar side effects as functions do, since [1,2,3] === [1,2,3] is false.

  10. Hi there is a mistake in the recording showing that exclduing count as dependency from useEffect will avoid cleanUp function from being called on every render. Your recording shows that ‘useEffect’ will be printed upon each execution of callback of setInterval, where as in reality it won’t. This is because you have excluded count variable from dependencies. So unless you have moved the console.log(“useEffect”) to your callback function passed to setInterval, the “useEffect” will be only printed once.

Leave a Reply