React 18 Alpha is coming, there are not many new features like React 17, V18 as the next big release of React focuses on Concurrent Mode which has been talked about for a long time.

So let’s take a look at what the new features will be.

Install React 18 Alpha

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

The new Root API

Reactdom.render is used to render the application component to the root element of the page

ReactDOM.render(<APP/>.document.getElementById( root ))
Copy the code

React 18 provides a new way to create the root object via reactdom. creatRoot, and then render it through the root object.

(Testing with CodeSandBox)

// index.js
import { StrictMode } from "react";
import ReactDOM from "react-dom";

import App from "./App";

const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);
root.render(
  <StrictMode>
    <App />{" "}
  </StrictMode>
);
Copy the code

Nodes are automatically batch rerendered

In React 17 and earlier, React does not automatically rerender components in batches when a browser event triggers a component batch status update to render the update.

But with the V18 new Root API mentioned above, all status updates will be automatically batch rerendered as they occur.

Exit the operation using reactdom.flushSync () if some key components do not want to be updated automatically

import { flushSync } from 'react-dom'; // Note: react-dom, not react

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
}

Copy the code

The new Suspense container component

The React 18 update has full support for Suspense, which, as the name suggests, allows temporarily unused components to be put on hold for lazy loading.

import "./styles.css";
import { useEffect, useState, useLayoutEffect, Suspense } from "react";
import { fetchProfileData } from "./fakeApi";

const initialResource = fetchProfileData();

function ProfilePage() {
  const [resource, setResource] = useState(initialResource);
  return (
    <>
      <Suspense
        fallback={
          <>
            <h1>Loading profile...</h1>
          </>
        }
      >
        <Sibling name="one" />
        <ProfileDetails resource={resource} />
        <Suspense fallback={<h1>Loading posts...</h1>} ><Sibling name="two" />
          <ProfileTimeline resource={resource} />
          <Sibling name="three" />
        </Suspense>
        <Sibling name="four" />
      </Suspense>
    </>
  );
}

function Sibling({ name }) {
  useLayoutEffect(() = > {
    console.log("Layout effect Sibling", name);
    return () = > {
      console.log("Layout cleanup Sibling", name);
    };
  });

  useEffect(() = > {
    console.log("Effect Sibling", name);

    return () = > {
      console.log("Cleanup Sibling", name);
    };
  }, [name]);

  console.log("Render sibling", name);
  return <h1>Sibling</h1>;
}

function ProfileDetails({ resource }) {
  useLayoutEffect(() = > {
    console.log("Layout effect ProfileDetails");
    return () = > {
      console.log("Layout cleanup ProfileDetails");
    };
  });

  useEffect(() = > {
    console.log("Effect ProfileDetails");
    return () = > {
      console.log("Cleanup ProfileDetails");
    };
  });
  const user = resource.user.read();
  return <h1>{user.name}</h1>;
}

function ProfileTimeline({ resource }) {
  const posts = resource.posts.read();
  useLayoutEffect(() = > {
    console.log("Layout effect ProfileTimeline");
    return () = > {
      console.log("Layout cleanup ProfileTimeline");
    };
  });

  useEffect(() = > {
    console.log("Effect ProfileTimeline");
    return () = > {
      console.log("Cleanup ProfileTimeline");
    };
  });

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.text}</li>
      ))}
    </ul>
  );
}

export default ProfilePage;

Copy the code

If Loading is not complete, the Loading component is displayed. After Loading, the Loading component is displayed.

The code is derived from romantic-architecture- HT3qi

The Suspense API is also unstable and not recommended for use in production

Suspense List

Suspense List for proposals in Concurrent Mode reactjs.org/docs/concur…

Suspense List serves as a container component for Suspense to help coordinate the many components that can be suspended by arranging the order in which these components are shown to users.

<SuspenseList revealOrder="forwards">
  <Suspense fallback={'Loading...'} >
    <ProfilePicture id={1} />
  </Suspense>
  <Suspense fallback={'Loading...'} >
    <ProfilePicture id={2} />
  </Suspense>
  <Suspense fallback={'Loading...'} >
    <ProfilePicture id={3} />
  </Suspense>. </SuspenseList>Copy the code
  • RevealOrder (Forwards, Backwards, Together) defines the order in which the SuspenseList sub-components should be displayed.

  • Tail (collapsed, hidden) specifies how to display the items not loaded in SuspenseList.

  • By default, SuspenseList displays all fallbacks in the list.

  • Collapsed only shows the next fallback in the list. Hidden Displays no information for an unloaded project.

  • Note that SuspenseList only operates on the most recent Suspense and SuspenseList components below it. It does not search deeper than a level boundary. However, you can nest multiple SuspenseList components within each other to build a grid.

startTransition API

This is a new API introduced in V18, which helps maintain current page responses and enables computatively complex, non-blocking UI updates at the same time. In the past, we might have added some stabilization to delay the calculation and rendering of the data. The new startTransition API allows us to mark the response data as Transitions for delayed processing.

The official working group proposed two application scenarios:

  • Slow rendering: React performs a lot of computation to transition the UI to display the results. (such as search engine keyword association)
  • Slow network: React is waiting for some data from the network. This use case is tightly integrated with Suspense. (Lazy loading)

The startTransition API allows developers to explicitly specify which UI renderings have higher priority and which ones need to be updated in real time and which ones need to be updated later

(Testing with CodeSandBox)

// APP.js
import "./styles.css";
import { useState, startTransition } from "react";

export default function App() {
  let [value, setValue] = useState(0);

  const onChange = (event) = > {
    startTransition(() = > {
      setValue(event.target.value);
      console.log(event.target.value);
    });
  };

  return (
    <div className="App">
      <input value={value} onChange={onChange} />
      <div>{value}</div>
    </div>
  );
}

Copy the code

All updates in the startTransition callback are considered non-urgent, and if a more urgent update occurs (such as a new value entered by the user), the update will be interrupted until there is no more urgent action to continue.

The actual test found that it seems not particularly friendly to Chinese input method, but so far no suitable solution has been found.

useDeferredValue

UseDeferredValue allows variables to be updated late. The API is not yet stable

import "./styles.css";
import { useState, useDeferredValue } from "react";

export default function App() {
  let [value, setValue] = useState(0);
  const deferredValue = useDeferredValue(value, { timeoutMs: 2000 });

  return (
    <div className="App">
      <div>{deferredValue}</div>
      <button onClick={()= >{setValue(deferredValue+1)}}>click me</button>
    </div>
  );
}

Copy the code

conclusion

React 18 (github.com/reactwg/rea… The React 18 API, useDeferredValue, has not yet been released, so we will use it next time. Here is the React 18 release schedule:

  • React 18 Alpha: Available now
  • Public Beta: at least a few months after Alpha
  • Release RC: at least a few weeks after the Beta release
  • Official: at least a few weeks after the RC release

Reference links:

Everything New in React 18

React 18!

Read the official blog: React18 is really here