DEV Community

Cover image for React Hooks Flow: A Deep Dive
Sai Maheshwar
Sai Maheshwar

Posted on

React Hooks Flow: A Deep Dive

Many developers know React, but a lack of understanding can lead to assumptions about how things work. Having a clear understanding of the hooks flow in React can greatly improve your code quality. After working with React for over 4 years, I'd like to share some key insights about the flow of React hooks, a concept that is often overlooked.

Before diving into hooks flow, I would like to revisit the rules of hooks

1. Only call Hooks at the top level
Don’t call Hooks inside loops, conditions, or nested
functions.Instead, always use Hooks at the top level of your
React function, before any early returns

2. Only call Hooks from React functions(Component or Custom Hook)
Don’t call Hooks from regular JavaScript functions.

React Hooks Flow

This React hooks flow diagram helps visualize the order in which hooks are called during different phases of a component's lifecycle.

React hook flow diagram

Let's explore each phase of the component lifecycle.

Initial Mount
This is when a component loads on the screen for the first time.

React component initial mount

Run lazy initializers
In React, state initialization occurs only once throughout a component's lifecycle.

By 'initializing,' I mean the initial value of useState will be assigned to the variable only once.

Image description

this is quite normal and usually not a concern. However, it becomes more important when initialization involves complex computations, such as setting state from local storage.

const [userList, setUserList] = useState(localStorage.getItem("usersList"))
Enter fullscreen mode Exit fullscreen mode

currently, localStorage.getItem("usersList") is executed on every re-render, but its result isn't assigned to the state variable. This repeated evaluation can lead to performance issues. To avoid this, you can pass a callback function to useState, which will only be executed once, during the mounting phase.

const [userList, setUserList] = useState(() => localStorage.getItem("usersList"))
Enter fullscreen mode Exit fullscreen mode

This is called lazy initialization of state, read more here

Lazy initialization helps prevent unnecessary initialization logic from running on every re-render.

Note: Only use the initializer function if there is a computation involved in state initialization.

Render
In this step React calls the function(component) to generate the virtual DOM representation of that component. This process does not directly mean that the component is visible to the user on the screen. Instead, it involves React creating a virtual DOM object that describes what the UI should look like.

Here's an example of a virtual DOM (VDOM) object:

const ComponentA = () => {
  return <h1>Hello World!</h1>
}
Enter fullscreen mode Exit fullscreen mode

VDOM object
{
$$typeof: Symbol(react.element),
key: null,
props: {children: 'Hello World!'},
ref: null,
type: "h1" ,
.....
};

React updates DOM
After generating the virtual DOM and reconciling it to get the final virtual DOM, React updates the actual DOM accordingly.

Run LayoutEffects
This step involves running the useLayoutEffect hook, which is similar to useEffect but executes before the browser performs any painting, see more here

Browser paints screen
Browser paints the DOM onto the screen

Run Effects
This is the step where the useEffect hook runs, i.e after rendering the UI on the browser

If there is a state update in a useEffect, it trigger the update lifecycle of the component

Update
When any state update is triggered, it triggers update lifecycle of the component

Image description

Render, React updates DOM
These steps are similar to the mounting phase

Cleanup LayoutEffects
After creating the virtual DOM (VDOM) and updating the actual DOM, React runs the cleanup functions for useLayoutEffect hooks.

Note: If the dependencies of a useLayoutEffect haven’t changed, its cleanup function will not run.

Run LayoutEffects
If any dependency comparison returns false, indicating a change, the useLayoutEffect will run again; otherwise, it will not.

Browser paints screen
At this point, the browser renders the updated DOM onto the screen.

Cleanup Effects, Run Effects
useEffect cleanup and execution happen only if there is a change in dependencies compared to the previous render. If no dependencies have changed, neither the cleanup function nor the effect will run.

Unmount
This is the final phase of a component's lifecycle, where the component is removed from the DOM and is no longer visible to the user.

Image description

Cleanup LayoutEffects, Cleanup Effects
Before removing a component from the DOM, React runs all cleanup functions for both useLayoutEffect and useEffect hooks.

Next time you encounter a bug in the UI, visualize the hooks flow to pinpoint the right spot in your code to investigate and resolve the issue. I hope this helps you improve your coding skills. Happy coding!

Top comments (0)