Hey, I am React with hooks. There's something apparently not many people tell you about how I work.

Photo by NIKHIL on Unsplash

Hey, I am React with hooks. There's something apparently not many people tell you about how I work.

A nuance on top of how React's hooks flow is usually taught

·

2 min read

Down the rabbit hole

Give me a component A and I'll:

On first render

  1. Run A's state lazy initializers.
  2. Render A.
  3. Update the DOM.
  4. Run A's layout effects.
  5. Paint the DOM updates from 3.
  6. Run A's effects.

On subsequent renders (props changed or state changed)

  1. Render A.
  2. Update the DOM.
  3. If any of A's layout effects don't have a dependency array or any of its dependencies has changed, run their clean-up functions.
  4. If any of A's layout effect's don't have a dependency array or any of its dependencies has changed, run them.
  5. Paint the DOM updates from 2.
  6. If any of A's effects don't have a dependency array or any of its dependencies has changed, run their clean-up functions.
  7. If any of A's effects don't have a dependency array or any of its dependencies has changed, run them.

When rendering your app doesn't render A anymore

  1. Run A's layout effects' clean-up functions.
  2. Run A's effects' clean-up functions.

The nuance

You have probably seen (if not, you should take a deep look!) this before: hook-flow.png It does an awesome job at explaining the order and the phases on which stuff happens, but even though most React devs understand when their effects run, I've seen them having a hard time understanding not every rerender trigger clean-ups.

When a new rerender happens, dependencies are checked. If any of the dependencies changed (or there's no dependencies array), it cleans up the previous effect before rerunning the effect.

What's a clean-up function?

The clean-up function run on the Nth render is the function returned by an effect on render Nth - 1. Beware! This means clean-up functions on render Nth will likely be closed over (hold a closure of) Nth - 1's state!

When does a dependency change?

React uses Object.is to compare dependencies. Object.is is an strict equality check (===) on esteroids: while the strict equality comparison algorithm is meant to lie about 0 === -0 and NaN === NaN to comply with IEEE 754, Object.is doesn't.

Try it yourself

Sandbox here.

Glossary

  • Render (and rerender): run a functional component's body or run a class component's render method. Obtaining the JSX returned from it and handing it to React so it knows how to update the DOM.
  • Update the DOM: perform DOM mutations through actual JS's DOM API. Updating the DOM synchronously schedules tasks to repaint the screen that will happen asynchronously.
  • Paint the DOM updates: giving the browser a break so it can paint any scheduled DOM update.