React18 new features

The React team officially released the 18th version of React on March 29, 2022. In this article, I will briefly introduce
the new features of React 18, the implementation of React Concurrent Mode (concurrent mode), and a brief upgrade guide.

New Features

Automatic Batching

React has been able to batch state updates long before React 18:

function App() {
    
    
  const [count, setCount] = useState(0);

  const [flag, setFlag] = useState(false);

  function handleClick() {
    
    
    setCount((c) => c + 1); // Does not re-render yet

    setFlag((f) => !f); // Does not re-render yet

    // React will only re-render once at the end (that's batching!)
  }

  return (
    <div>
      <div>{
    
    count}</div>
      <button onClick={
    
    handleClick}>Next</button>
    </div>
  );
}

In the above example, when the user clicks the button, the state will be updated twice. It stands to reason that each state update will cause a re-render. However, these two updates can be synthesized once, thereby reducing the performance loss caused by unnecessary re-render.

This batching is limited to updates inside React's native events.

In React 18, the scope of operations supported by batch processing has been expanded: Promise, setTimeout, native event handlers, etc. The internal updates of these non-React native events will also be merged:

// Before: only React events were batched.

setTimeout(() => {
    
    
  setCount((c) => c + 1);

  setFlag((f) => !f);

  // React will render twice, once for each state update (no batching)
}, 1000);

// After: updates inside of timeouts, promises,

// native event handlers or any other event are batched.

setTimeout(() => {
    
    
  setCount((c) => c + 1);

  setFlag((f) => !f);

  // React will only re-render once at the end (that's batching!)
}, 1000);

Transitions

Transitions is one in React that is used to distinguish high-quality updates from non-high-quality updates 新概念.

  • High-quality update/rendering: Including mouse clicks, typing and other update scenarios that require high real-time interactivity, the freeze will affect the user's interactive behavior, making the user obviously feel that the entire page is stuck.

  • Non-high-quality update/rendering: ordinary UI update, not related to user interaction, and some scenarios that do not have high requirements for real-time update.

Suspense

Suspense is an API provided by React for declaring the UI loading state:
<ComponentThatSuspends /> <Sibling /> </Suspense>
in the above string of codes, when the component ComponentThatSuspends requests data processing, React will display the Loading component in its place.

Suspense is also available in React 16 and 17, but it is not complete and many features are not yet ready. In the plan of the React team, the complete body of Suspense is based on Concurrent React, so in React 18, Suspense has some changes compared to before.

Suspense for SSR

In the SSR before React 18, the client must wait for the HTML data to be loaded on the server at one time and wait for all JavaScript to be loaded before starting hydration, and wait for all components to be hydrated before they can interact. That is to say, the whole process needs to complete the process from getting data (server) → rendering to HTML (server) → loading code (client) → hydrating (client). Such SSR does not make our fully interactive faster, but only improves the speed at which users perceive static page content.

React 18 的 Suspense:

  • <script>The server can send HTML without waiting for the component wrapped by Suspense to be loaded. Instead, the component wrapped by Suspense is the content in the fallback, usually a placeholder (spinner), and the position of the HTML is marked with the smallest inline tag . After waiting for the component's data to be ready on the server, React then sends the rest of the HTML into the same stream.

  • The process of hydration is step-by-step, and there is no need to wait for all js to be loaded before starting hydration, which avoids page lag.

  • React will listen to interactive events on the page in advance (such as mouse clicks), and give priority to hydration on the area where the interaction occurs.

Concurrent Rendering

The most important update in React 18 is the full enablement of concurrent rendering. It's not really a new feature, it's actually a major change to how React works internally. React layouts have long been around for the ultimate in concurrent rendering.

question

In scenarios where there are many page elements and frequent re-rendering is required, React 15 will experience frame drop. The root cause is that a large number of simultaneous computing tasks block the browser's UI rendering. JS operations, page layout and drawing are all run in the main thread of the browser, and they are mutually exclusive. If the JS operation continues to occupy the main thread, the page cannot be updated in time. When we update the state to trigger re-render, React will traverse all the nodes of the application, calculate the difference, and then update the UI. Once the update starts, it cannot be interrupted in the middle, and the main thread cannot be released until the entire tree has been traversed. If there are many elements on the page, the entire process may take more than 16ms, causing the browser to freeze.

It can be seen that the key to browser freeze caused by the implementation of React 15 is that every time re-render starts, it cannot be stopped, so the React team thought of a solution: change re-render to 可中断 .

train of thought

  • The JS calculation during re-render is split into smaller granular tasks, and the executed tasks can be paused, continued and discarded at any time.

  • When the calculation time of JS reaches 16 milliseconds, it will be paused, and the main thread will be given to the UI to draw, so as to prevent the problem of rendering frame drop.

  • Continue to execute small tasks that were not executed before when the browser is idle.

Upgrade Guide

  • Change the mounting method of the root node to use the new API createRoot, and the old API is still compatible. Only after using createRoot will there be new features of React 18.

  • React 18 will enable the automatic batch processing mentioned above, which is considered a breaking change, but React also provides a flushSync API to exit the automatic batch processing, the usage is as follows:

import {
    
     flushSync } from "react-dom";

function handleClick() {
    
    
  flushSync(() => {
    
    
    setCounter((c) => c + 1);
  });
  // React has updated the DOM by now

  flushSync(() => {
    
    
    setFlag((f) => !f);
  });
  // React has updated the DOM by now
}
  • If flushSync is not used, the two setStates will only re-render once, and will be triggered twice after use.

  • Big change in TS type definition: If children are used, its type needs to be written in the definition of component props, which can be ignored in the past.

interface MyButtonProps {
    
    
  color: string;

  children?: React.ReactNode;
}
  • React 18 no longer supports IE.

Guess you like

Origin blog.csdn.net/hyqhyqhyqq/article/details/129675202