Categories
JavaScript React

Built-in React Hooks —useLayoutEffect and useDebugValue

Spread the love

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we look at the useLayoutEffect and useDebugValue hooks.

useLayoutEffect

useLayoutEffect has an identical signature to useEffect , but it fires synchronously after all DOM mutations are done.

This is useful for reading layout from the DOM and synchronously re-render.

Updates inside useLayoutEffect will be flushed synchronously before the browser has a chance to paint.

To prevent blocking visual updates, we should use useEffect whenever possible.

useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate .

We should only use useLayoutEffect if useEffect isn’t working properly.

If server rendering is used, the useLayoutEffect nor useEffect are run until the JavaScript is downloaded.

React warns when server-rendered component contains useLayourEffect .

To exclude components that need layout effects from server-rendered HTML, we render it conditionally with showChild && <Child /> and defer showing it with useEffect(() => { setShowChild(true); }, []).

Then the UI won’t appear broken before rendering is done.

For example, we can render synchronous with useLayoutEffect as follows:

function App() {  
  const [value, setValue] = React.useState(0);  
  React.useLayoutEffect(() => {  
    if (value === 0) {  
      setValue(10 + Math.random() * 200);  
    }  
  }, [value]); 

  return (  
    <>  
      <button onClick={() => setValue(0)}>Random Value</button>  
      <p>{value}</p>  
    </>  
  );  
}

Since value is set initially to 0, we want to update that first before rendering, so we use useLayoutEffect hook and call setValue in the callback.

Also, since we set value to 0 when clicking the button, we want to only show the value when value when it’s not 0, so useLayoutEffect will prevent 0 from being shown.

useDebugValue

useDebugValue is used to display a label for custom hooks in React DevTools.

It takes any value that we want to display.

For example, we can use it as follows:

import React, { useEffect, useState } from "react";  
import ReactDOM from "react-dom";  
const useDelayedMessage = (msg, delay) => {  
  const [message, setMessage] = useState("");  
  useEffect(() => {  
    setTimeout(() => {  
      setMessage(msg);  
    }, delay);  
  });  
  React.useDebugValue(message ? "Message Set" : "Message not set");  
  return message;  
};

function App() {  
  const delayedMessage = useDelayedMessage("foo", 1500);  
  return <div>{delayedMessage}</div>;  
}

Since we have:

React.useDebugValue(message ? "Message Set" : "Message not set");

in React DevTools, we’ll see the Message not set message when the page first loads, and then when message is set after the delay , then we see Message set .

This hook is useful for custom hooks that are part of shared libraries

Defer formatting debug values

In some cases formatting, a value for display may be an expensive operation.

Therefore, useDebugValue accepts a formatting function as an optional second parameter. The function is only called if the hooks are inspected.

It receives the debug value as a parameter and returns the formatted display value.

For example, we can write:

import React, { useEffect, useState } from "react";  
import ReactDOM from "react-dom";  
const useDelayedMessage = (msg, delay) => {  
  const [message, setMessage] = useState("");  
  useEffect(() => {  
    setTimeout(() => {  
      setMessage(msg);  
    }, delay);  
  });  
  React.useDebugValue(message, message =>  
    message ? "Message Set" : "Message not set"  
  );  
  return message;  
};

function App() {  
  const delayedMessage = useDelayedMessage("foo", 1500);  
  return <div>{delayedMessage}</div>;  
}

In the code above, we have:

React.useDebugValue(message, message =>  
    message ? "Message Set" : "Message not set"  
  );

which runs the formatting function in the second argument when it’s inspected.

The message parameter has the same value as message returned from useState .

Conclusion

We can use the useLayoutEffect hook to synchronous run code after all DOM mutations are done.

useDebugValue hook is handy for debugging with React DevTools since it lets us display something in the DevTools console as the hook runs.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *