React 18 – 新功能和改进策略

3 月 8 日,React 团队发布了 React 18 RC(Release Candidate )。最新版本带来了许多新功能,这些功能将改变许多应用程序中的编码模式。它带来了一些性能改进,我将在本博客中介绍这些改进。

并发

并发性是多个进程同时执行,并且可能相互交互也可能不交互的系统的属性。太复杂了?让我们分解一下。假设有一场比赛正在进行中。现在,并发性是有多少人在并行赛道上为一场比赛而奔跑。

并发

并发性是 React 18 引入的一项新功能。这是一种新的幕后机制,使 React 能够同时准备多个版本的 UI

在这种机制中,与以前的情况不同,React 可能会开始渲染,在中间暂停一些关键任务,然后再次恢复渲染。唯一要记住的是,它也可能完全放弃过程中的渲染。React 保证 UI 看起来一致,即使渲染中断也是如此。

这赋予了 React 在后台准备屏幕的能力 – 而不会阻塞新线程!

服务器端渲染的悬念

服务器端渲染中的悬念

React 在服务器端渲染框架(如 Next.js Relay、Hydrogen 或 Remix)中引入了 Suspense 的功能。React 18 引入了:
在服务器上进行代码拆分并具有悬念,并在
服务器上进行流式处理渲染

自动配料

批处理是 React 将多个状态更新分组到单个重新呈现中以获得更好的性能优化的现象。GIFBatching

在 React 18 之前,对基于 react 的事件处理程序执行批处理更新。但是,对于承诺、setTimeout、本机事件处理程序或任何其他事件,未执行批量更新。React 18 也会对上述情况执行自动批量更新。

让我们使用代码来理解这一点。

setTimeout(() => {
  setCount(count => count + 1);
  setFlag(flag => !flag);
  // React will only re-render once at the end (that's batching!)
}, 1000);

同样,上面的代码的行为与此相同:

fetch(/*...*/).then(() => {
  setCount(counter => counter + 1);
  setFlag(flag => !flag);
  // React will only re-render once at the end (that's batching!)
})

如果您不想批处理,可以使用 ReactDOM.flushSync() 。让我们用一些代码来理解

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

function handleFlushesClick() {
  flushSync(() => {
    setCounter(counter => counter + 1);
  });
  // React has updated the DOM by now
  flushSync(() => {
    setFlag(flag => !flag);
  });
  // React has updated the DOM by now
}

转换

此功能可区分紧急更新和非紧急更新。紧急更新是需要立即响应的更新。紧急更新包括单击、按下、键入等操作 – 需要立即响应或用户希望 UI 立即响应的内容。
屏幕上不会显示中间值。动图Transition example

一个现实生活中的例子

考虑一个现实生活中的例子,让我们想想一个去抖动的打字机。现在,当您键入输入时,您希望输入框反映键入的值。但是,您是否希望结果立即出现?不对!它会反弹,然后你得到结果。因此,从您键入输入到获得建议的时间有一些过渡时间。此时间范围将用于过渡。

通常,为了获得最佳用户体验,单个用户输入应同时导致紧急和非紧急更新。

import {startTransition} from 'react';

// Urgent: Show what was typed
    setInputValue(input);`

// Mark any state updates inside as transitions
  startTransition(() => {
     // Transition: Show the autosuggestion based on the input 
        value
      setSearchQuery(input);
});

动图Search bar

Another real-time example

const [isPending, startTransition] = useTransition()

Here the useTransition hook has 2 parameters that is destructured.

isPending : to denote if the UI update is still in transition state

startTransition: A function that executes code for transactions.

function handleClick() {
   startTransition(() => {
     setTab('comments');
   });
}

This function gets called when you want to switch from Photos tab to Comments tab.


<Suspense fallback={<Spinner />}>
<div style={{ opacity: isPending ? 0.8 : 1 }}>
{tab === 'photos' ? <Photos /> : <Comments />}
</div>
</Suspense>

During the transition phase, while the new UI is being prepared by React, the tab with the Photos UI will be now shown to the user with 80% opacity to give a smooth view of transition.

Strict Mode in React

The Strict Mode in development server brings forth a couple of interesting changes in React 18. This mode essentially provides out-of-box performance for React.

This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.

The series of events during mounting now:

I. React mounts the component.

  • Layout effects are created.
  • Effects are created.

II. React simulates unmounting the component.

  • Layout effects are destroyed.
  • Effects are destroyed.

III. React simulates mounting the component with the previous state.

  • Layout effects are created.
  • Effects are created.`

During unmounting, the following events occur

I. Layout effects are destroyed and Effect effects are destroyed.

New Hooks

Image description

a. useId

useId is a new hook for generating** unique IDs on both the client and server*, while avoiding hydration mismatches. This generates an **unique string containing : which does not collide with css selectors and querySelectorAll*

You can also use userId with identifierPrefix in order to prevent collision in multi-root applications. For multiple IDs in the same component, append a suffix using the same id.

b. useDeferredValue

useDeferredValue will let you defer re-rendering a non-urgent part of the tree. Remember we talked about non-urgent rendering? It is no fixed time delay, so React will attempt the deferred render right after the first render is reflected on the screen.

c. useSyncExternalStore

useSyncExternalStore 是一个新的挂钩,它允许外部存储通过强制对存储的更新进行同步来支持并发读取。它消除了在实现对外部数据源的订阅时对 useEffect 的需求。

代码片段:

   const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot]);

subscribe:用于注册每当存储更改时调用的回调的函数。
:返回存储的当前值的函数。
:返回服务器呈现期间使用的快照的函数。getSnapshotgetServerSnapshot

d. 使用插入效果

useInsertionEffect(didUpdate);

useInsertionEffect 是一个新的钩子,它允许 CSS-in-JS 库解决在渲染中注入样式的性能问题。此挂钩将在 DOM 发生突变后运行,但在布局效果读取新布局之前运行。

此挂钩将有助于计算与并发重新渲染同步的布局。


结论

还有其他一些小而重要的更新 – 例如使用createRoot()钩子而不是ReactDOM.render。此方法将用于呈现 DOM 元素并使用 root.unmount() 进行 umount

除了 React 之外,还为使用 renderToPipeableStream& renderToReadableStream 的服务器提供流式悬念支持

React 开发人员一直专注于此发布版本中的增强和改进以及一些错误修复。更新并不细致,可以在早上的会议中完成。那么,等待应用程序开发人员的是什么呢?让我们升级我们的库并开始工作!向 React 团队致敬!

发布者:小站,转转请注明出处:http://blog.gzcity.top/45.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2017年4月25日 14:28
下一篇 2022年4月23日 12:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

评论列表(2条)