React 18 Alpha has been released, with new features and apis focused on user experience and performance improvements

The installation

npm install react@alpha react-dom@alpha
Copy the code

Root API

  • Leacy root API: reactdom.render ()
  • New root API: reactdom.createroot ()

The difference

The old root API

import React from 'react';
import ReactDOM from 'react-dom';

const container = document.getElementById('root') 

ReactDOM.render(<App />, container);
Copy the code

New Root API (React 18)

import * as ReactDOM from 'react-dom';
import App from 'App';

const container = document.getElementById('app');

// Create a root node
const root = ReactDOM.createRoot(container);

// Initial render: Render elements to the root node
root.render(<App tab="home" />);

// There is no need to pass the container when updating
root.render(<App tab="profile" />);
Copy the code

hydration

Tells function moves before hydrateRootAPI:

import ReactDOM from 'react-dom';
import App from 'App';

const container = document.getElementById('app');

ReactDOM.hydrate(<App tab="home" />, container);
Copy the code

After:

import ReactDOM from 'react-dom';
import App from 'App';

const container = document.getElementById('app');

// Build and render chocolate.
const root = ReactDOM.hydrateRoot(container, <App tab="home" />);

// It can be updated later
root.render(<App tab="profile" />);
Copy the code

render callback

In the old root API, Render accepted a callback

import ReactDOM from 'react-dom';
import App from 'App';

const container = document.getElementById('app');

ReactDOM.render(container, <App tab="home" />.function() {
  // called after initial rendering or update
  console.log('rendered'.)});Copy the code

New root API

import * as ReactDOM from 'react-dom';
import App from 'App';

const rootElement = document.getElementById('app');

ReactDOM.createRoot(rootElement).render(<App callback={()= > console.log("renderered")} />);
/ / or
ReactDOM.createRoot(rootElement).render(<App />);
requestIdleCallback(callback);
/ / or
ReactDOM.createRoot(rootElement).render(<App />);
setTimeout(callback, 0);
Copy the code

Automatic batching

Batch updates refer to multiple states, not multiple updates of one state.

The difference

Before:

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

  function handleClick() {
    setCount(c= > c + 1);
    setFlag(f= >! f);// Two properties are updated, but React only renders once
  }
  
  function handleClick2() {
    fetchSomething().then(() = > {
      // React 17 and before will not be batch updated
      setCount(c= > c + 1); // Causes a re-render
      setFlag(f= >! f);// Causes a re-render
    });
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black}} ">{count}</h1>
    </div>
  );
}
Copy the code

Before React 18, only React event handlers were batch updated. Promises, setTimeout, native events, and other events were not batch updated. In Act18, there are batch updates in promises, setTimeout, native events, and other events. After:

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

  function handleClick() {
    fetchSomething().then(() = > {
      // React 18 and use the New root API
      setCount(c= > c + 1);
      setFlag(f= >! f);// only render once
    });
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black}} ">{count}</h1>
    </div>
  );
}
Copy the code

Don’t want to batch update?

import { flushSync } from 'react-dom';

function handleClick() {
  flushSync(() = > {
    setCounter(c= > c + 1);
  });
  React now updates the DOM
  flushSync(() = > {
    setFlag(f= >! f); });React now updates the DOM
}
Copy the code

startTransition()

In React, if the UPDATED DOM tree is large, ODM comparison takes a long time, which may lead to unresponsive pages and stalling. StartTransition () solves this problem. Take an example: enter text in the input box, and display a list of prompts according to the input text query data.

// Pressing: displays input text
setInputValue(input);

// Not pressing: displays the query result
setSearchQuery(input);
Copy the code

If there are a lot of results at this point, synchronizing the render result list may cause the input box to stall. React 18 prior to React 18 all updates were rendered simultaneously.

// Pressing: display text
setInputValue(input);

/ / state
startTransition(() = > {
  // Transition: Displays the result
  setSearchQuery(input);
});
Copy the code

Means that the state update of the startTransition flag can be interrupted by a more urgent update. Avoid page lag.

Suspense

<Layout>
  <NavBar />
  <Sidebar />
  <RightPane>
    <Post />
    <Suspense fallback={<Spinner />} ><Comments />
    </Suspense>
  </RightPane>
</Layout>
Copy the code

In Suspense/>, React can skip the request for comment data and continue parsing the rest of the HTML. This will not block.

useDeferredValue

Text that does not require urgent display can be delayed for a certain amount of time, reducing the update priority

const deferredValue = useDeferredValue(value, { timeoutMs: 3000 });
Copy the code

The article may have some misunderstanding, please correct it

React 18 All updates to the discussion list