Last week, the React website released react@rc as a Release Candidate, which means the API is stable and will not be much different from the final version. The website also published a blog called how to Upgrade to REact18 RC to encourage people to try it out. So we can use it in the project team! The following is a translation of the official document.
The text start
If you want to help us test React 18, please follow the steps in this upgrade guide and report any problems you encounter so we can fix them before the stable release.
Note: React Native users: React 18 will be released in React Native with the New React Native Architecture. For more information, see React Conf Keynote Here.
The installation
Install the latest version of React 18 RC using the @rc tag
npm install react@rc react-dom@rc
Copy the code
Or use YARN
yarn add react@rc react-dom@rc
Copy the code
Updates to the client rendering API
1. Replace render function with createRoot
If you’re installing React 18 for the first time, you’ll see the following warning on the console:
Use createRoot instead. Until you switch to the new API, your app will behave as if it’s running React. Reactjs.org/link/switch…
This is due to using the existing API called by reactdom.render. This creates a root running in “legacy” mode, which works exactly as React 17 does. Prior to release, React added a warning to the API indicating that it had been deprecated and switched to the new Root API.
React 18 introduced a new Root API that supports concurrent renderer capabilities, which you can decide whether to enable or not.
/ / before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);
/ / now,
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
// Initial render renders the node to the following node
root.render(<App tab="home" />);
// After the update, there is no need to pass dom nodes
root.render(<App tab="profile" />);
Copy the code
React changed this API for several reasons.
First, this fixes some engineering issues with the API running updates. As shown above, in the Legacy API, you need to pass the container element to Render multiple times, even if it never changes. This also meant that we didn’t need to store the root element on the DOM node, although we still do that today.
Second, this change allows us to remove the Hydrate method and replace it with an option on root; Remove render callbacks, which are meaningless in some variations of Chocolate.
The DOM destruction API has also been changed and unmountComponentAtNode has been changed to root.unmount:
/ / before
unmountComponentAtNode(container);
/ / now,
root.unmount();
Copy the code
At the same time, the render function’s callbacks are also missing, because generally they don’t work out as expected when using the Suspense API:
/ / before
const container = document.getElementById('app');
ReactDOM.render(<App tab="Home" />, container, () = > {
console.log('rendered');
});
// Now you need to redefine a function to call back and forth using useEffect
function AppWithCallbackAfterRender() {
useEffect(() = > {
console.log('rendered');
});
return <App tab="Home" />
}
const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);
root.render(<AppWithCallbackAfterRender />);
Copy the code
Hydrate upgraded to hydrateRoot
Hydrate is a process by which ReactDOM reuses content rendered by the ReactDOMServer server with as much structure as possible and complements client-specific content such as event bindings.
The Hydrate function will be moved to the hydrateRoot API.
Before:
import * as ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
// Render with hydration.
ReactDOM.hydrate(<App tab="home" />, container);
Copy the code
Now:
import * as ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
// Create *and* render a root with hydration.
const root = ReactDOM.hydrateRoot(container, <App tab="home" />);
Unlike createRoot, there is no need for a separate root.ender() call
Copy the code
Note that unlike createRoot, hydrateRoot accepts native JSX as a second parameter. This is because the initial client rendering is special and needs to match the server tree.
If you want to update root again after hydration, you can save it to a variable, as with createRoot, and then call root.render() :
import * as ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
// Create *and* render a root with hydration.
const root = ReactDOM.hydrateRoot(container, <App tab="home" />);
// You can later update it.
root.render(<App tab="profile" />);
Copy the code
Updates to the server rendering API
In this release, The React/dom/server API has been improved to fully support Suspense and streaming SSR on the server side. Node.js streaming apis that do not support Suspense will be deprecated completely:
renderToNodeStream
Deprecated ⛔ ️ ️- Instead, for streaming media in the Node environment, use:
renderToPipeableStream
.
A new API, renderToReadableStream, has also been introduced to support streaming SSR and Suspense, and to provide support for modern edge runtime environments such as Deno and Cloudflare Workers:
RenderToString and renderToStaticMarkup are still available, but Suspense support is not as friendly.
Finally, the renderToStaticNodeStream API will continue to be used for rendering emails
For more information, please see Working Group Discussion here.
Automatic Batching
React batching is simply the merging of multiple state updates into a single re-render. Due to design issues, React could only be batched in component lifecycle functions or composited event functions prior to React 18. By default, promises, setTimeout, and other asynchronous callbacks are not optimized for batch processing.
React combines multiple state updates into a single re-render for better performance. Before React 18, React merged multiple setstates in an event into one. Promises, setTimeout, and other asynchronous events did not merge.
// React 18
function handleClick() {
setCount(c= > c + 1);
setFlag(f= >! f);// In compositing events, enjoy batch optimization and only re-render once
}
setTimeout(() = > {
setCount(c= > c + 1);
setFlag(f= >! f);// No batch processing is performed, and two re-renders are triggered
}, 1000);
Copy the code
Starting with React 18, if you use createRoot, all updates will be optimized for batch processing, including Promise, setTimeout, and other asynchronous callback functions.
// React 18
function handleClick() {
setCount(c= > c + 1);
setFlag(f= >! f);// Will only be re-rendered once
}
setTimeout(() = > {
setCount(c= > c + 1);
setFlag(f= >! f);// Will only be re-rendered once
}, 1000);
Copy the code
If you have special rendering needs and don’t want to batch, you can also use flushSync asynchronously:
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() = > {
setCounter(c= > c + 1);
});
/ / update the DOM
flushSync(() = > {
setFlag(f= >! f); });/ / update the DOM
}
Copy the code
Learn more about Automatic Batching deep Dive
Apis for third-party libraries
Some library maintainers have created new apis that require concurrent rendering in areas such as style external storage and accessibility, and some libraries may switch to one of the following apis
useId
It’s a new oneHook
Is used to generate unique ids on both client and server while avoidinghydration
The incompatibility of this can be solvedReact 17
And lower versions of the problem.useSyncExternalStore
It’s a new oneHook
Allows external storage to support concurrent reads by forcing synchronous updates. This new API is recommended for any library that integrates with React external states. For more information, see the useSyncExternalStore Overview article and useSyncExternalStore API details.useInsertionEffect
It’s a new oneHook
It can be solvedCSS-in-JS
Performance issues with libraries injecting styles dynamically in renderings.
React 18 also introduces new apis for concurrent rendering, such as startTransition and useDeferredValue, which will be shared more in an upcoming stable release.
Update Strict Mode
In the future, React hopes to add a feature that allows React to add and remove parts of the UI while preserving state. For example, React should be able to display the previous screen immediately when the user TAB goes away from the screen and comes back. To do this, React unmounts and remounts the tree using the same component state as before.
This feature will give React better out-of-the-box performance, but requires components to be resilient to multiple mount and destroy effects. Most effects work without any changes, but some effects assume they are installed or destroyed only once.
To help surface these issues, React 18 introduces a new development – check only strict mode. Each time a component is mounted for the first time, this new check automatically unmounts and remounts each component, restoring the previous state on the second mount.
Configure your test environment
When you first update with createRoot, you might see this warning in the console:
The current testing environment is not configured to support act(…)
To fix this, set GlobalThis. IS React Act Act Environment to true before running the test:
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
Copy the code
The flag tells React that it’s running in an environment similar to a unit test. If you forget to wrap the update with ACT, the response logs useful warning information.
You can also set the flag to false to tell React that the act is unnecessary. This is useful for simulating end-to-end testing of a full browser environment.
Eventually, we want the test library to automatically configure this functionality for you. For example, the next version of React Testing Library has built-in support for React 18 without requiring any additional configuration.
The name of the act is from the arrange-act-Assert mode.
Internet Explorer is no longer supported
React drops support for Internet Explorer in this release, it will lose support on June 15, 2022. React made the change because the new features introduced in React 18 were built using features of modern browsers, such as microtasks, that aren’t polyfilled enough in IE.
Other changes
- Update to remove “setState on unMounted Component” warning
- Suspense is no longer needed
fallback
Prop to capture - Components can now render undefined
- Deprecated renderSubtreeIntoContainer
- StrictMode is updated to default to no silent double logging
If you want to learn more, check out the React blog: reactjs.org/blog/2022/0…
That’s all the content of this article. I hope this article is helpful to you. You can also refer to my previous articles or share your thoughts and experiences in the comments section.
This article first nuggets platform, source ma blog