Replace Legacy Root API's Callback Argument

Michael Chan
InstructorMichael Chan
Share this video with your friends

Social Share Links

Send Tweet
Published 3 years ago
Updated 3 years ago

React's legacy root API (render) took a callback function. React called this function once the post-render. With new streaming capabilities scheduled for React 18, this feature becomes unpredictable. Replace it with a ref callback — or one of these other strategies.

Instructor: [0:01] ReactDOM's legacy root API allowed us to pass in a callback function that would get called as soon as React rendered. It would get passed in something like console.log("React rendered")

[0:12] If we try that with the new createRoot API, we get an error, "Warning -- Render does not support the second callback argument. To execute a site effect after rendering, declare it in a component body with useEffect()."

[0:26] There's several recommendations for how to solve this, but let's follow this warning first. Let's take out the second argument and move it into our apps component body with a useEffect(). Paste it in, and our error goes away. We also see this rendered out to the console.

[0:47] With a legacy root API, this only rendered the first time. To get parity with that, we would need to add an empty array to this useEffect(). Doesn't change the result except for the fact that it will only render on that first render.

[1:01] Of course, there's another option if you don't want to modify this component. Let's copy this, comment that out. We can use setTimeout() or requestIdleCallback() right after calling ReactDOM.createRoot(). window.setTimeout() -- handy little autocomplete there -- you change this to zero and paste in our function. Clear this that we don't need.

[1:27] What this does is a little bit different. Get the same result in this simplified app, but this version isn't precisely coordinated with React rendering. It will simply render as soon as React yields two low-priority updates.

[1:42] There's a third option that might come in handy to you if you need a ref to the DOM node that React rendered to. Here, we can provide a callback as a prop, take the ref as an argument, and log it out, ref.tagName.

[2:00] On the component side, we take that callback as a prop and use ref on this React element. Save, refresh, and we have access to that DOM element that React rendered.