Home

CV

Blog

Brand

When to use the useEffect and useLayoutEffect hooks.

Liam Hales

Liam Hales

Senior Software Engineer

TypeScript

React

November 2021 - 3 years ago

Introduction.

Have you ever experienced flickering UI when using
React
right after the page renders in your browser? Maybe you see some default text state for a fraction of time beofre seeing the correct text state displayed on your screen. This issue is caused by updating such sate with the incorrect hook
useEffect
, in this scenario
useLayoutEffect
should be used instead.
 

Which one should I use?.

The two hooks are almost identical, the only difference is
useEffect
runs asynchronous and
useLayoutEffect
runs synchronously after all
DOM
mutations but before the browser renders the page.

useEffect

The
useEffect
hook should be used 99% of the time and should be the go too hook out of the two. Always use it over
useLayoutEffect
unless you have reason too. Most of the time you are updating state and making calls to API's way after the browser has rendered when the user interacts with the components, so
useEffect
will work just fine.

useLayoutEffect

As mentioned above
useLayoutEffect
runs synchronously after all
DOM
mutations but before the browser renders the page which basically means all updates within
useLayoutEffect
will run before anything is shown on the page to the user. This should be used when doing something such as measuring components or when you want to update some state from some initial value before the page is rendered to the user.
 

The problem.

Let's take a simple example of some text state which will be displayed to the user and updated to some other value using the
useEffect
hook.
const App: FunctionComponent = (): ReactElement => {

  const [text, setText] = useState('Loading...');

  useEffect(() => {
    setText('Hello World!');
  }, []);

  return (
    <p>{text}</p>
  );
};
If you run this component yourself you will see the
Loading...
text flicker for a fraction of time before you see
Hello World!
, but why when the state is being updated as soon as the component mounts?
This is because the
DOM
is mutated and the browser is rendering the page to the user before the
useEffect
hook is called resulting in the
Loading...
default value being visible first before it is updated and redrawn on the screen.
 

The solution.

The solution is to simply use
useLayoutEffect
instead of
useEffect
which will cause the hook to be called after the
DOM
is mutated but before the browser renders the page to the user resulting in the
Loading...
default value never being shown, fixing the flicker issue.
useLayoutEffect(() => {
  setText('Hello World!');
}, []);
 

Summary.

Remember, the
useEffect
hook should be used 99% of the time. However a good tip when deciding which hook to use is to start with
useEffect
first and if you come across any UI flickering issues, you can then try and use
useLayoutEffect
for updating the state which powers the UI that is flickering.

Get in touch

Thank you for stopping by! Please feel free to contact me with any questions you may have, I’ll try my best to get back to you.

2024 - Liam Hales

Designed & Built by Liam Hales