13
votes

How do we mimic the functionality of useLayoutEffect() in a class component?

Suppose our functional component is

function MyFuncComponent() {
  useLayoutEffect(() => {
    runSideEffect();
  });
}

Assuming this particular side effect requires no cleanup, is this following code equivalent?

class MyClassComponent extends React.Component {
  componentDidMount() {
    runSideEffect();
  }
  componentDidUpdate() {
    runSideEffect();
  }
}

From the doc, it seems they are not exactly equivalent, as multiple scheduled useLayoutEffect()s are flushed in between consecutive renders, but componentDidUpdate()s aren't. Is this understanding correct and if so, how do we mimic useLayoutEffect()?

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

1
Try getSnapshotBeforeUpdate. it should probably work. - Ravi Theja

1 Answers

1
votes

according to the doc

If you’re migrating code from a class component, note useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate. However, we recommend starting with useEffect first and only trying useLayoutEffect if that causes a problem.

So if you want your side effect to run in a class component with the same behaviour you gotta use componentDidMount and componentDidUpdate like you thought. The difference between useEffect and useLayoutEffect is that useEffect only runs after the DOM has been updated (the effect will run after the render is committed to the screen). useLayoutEffect will trigger the effect right after the DOM mutations are computed. Therefore, updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.

Here there's a good explanation about useEffect and useLayoutEffect. But thinking on class components, it's equivalent to componentDidMount and componentDidUpdate because it is the commit phase. That's the phase where changes to DOM are allowed to happen as well as side effects and scheduled updates. Both componentDidMount and componentDidUpdate have the synchronous behaviour just like useLayoutEffect. useEffect is the usual recommended option because it won't block the browser rendering which is better for performance in most cases, being an optimized hook version of componentDidMount and componentDidUpdate.