头图

Learn the new features of React18 together

Passing by: React17

New features of React17: For users, there are no new features, official words:

The React 17 release is unusual because it doesn't add any new developer-facing features. Instead, this release is primarily focused on making it easier to upgrade React itself.

Event system refactoring

As an in-depth user of the React library, I personally like this All In Js development method. The entire page logic can be written in js instead of constantly switching between html and js and designing each other;

But another important point is that the development process does not need to consider the cross-browser compatibility of events, because React has made mainstream browser compatibility through SyntheticEvent.

Although the usage is mostly the same, it is not exactly the same as the native event. The differences are:

  • The mounting mechanism of event nodes, React uses all node events to be mounted on the document node, and adopts the mechanism of event delegation and registration distribution;
  • The timing of event triggering is inconsistent. Although they all follow the downward capture and upward bubbling, the synthetic event will be 晚一拍 ; the specific performance is, native event capture -> native event bubbling -> react event capture -> react event bubbling Bubble;
  • The input parameters of the callback event are different. The native one is the event object, and the React one is the synthetic event object, and it has its own event pool to manage these objects;

React 17 has refactored the event system, and its changes:

20220524094816

  • The mounting mechanism of the event node is changed from document to root node, and this change will not cause Portals monitoring outside the root node to fail;
 import React from 'react';
import ReactDOM from 'react-dom';

class Foo extends React.Component {
  enter(e){ console.log('click foo');
  e.stopPropagation(); }
  render() {
    return <div style={{ height: 30, background: 'blue' }} onClick={this.enter}>Foo</div>;
  }
}

export default class Bar extends React.Component {
  enter(e){ console.log('click bar'); }
  componentDidMount() {
    ReactDOM.render(<Foo />, this.refs.c);
  }
  render() {
    return <div style={{ height: 50, background: 'red', color: 'white' }} onClick={this.enter}>Bar <div ref="c"/></div>;
  }
}

Looking at the above example, the page UI is as follows. If it was before 17, when we clicked on the Foo area, we expected the Bar area not to respond. Even if stopPropagation was added, it could not be prevented; but with the arrival of 17, this bug can be avoided. This is also to pave the way for 渐进式升级
20220528234609

  • Event callback timing is in sync with native events (this is really a big improvement);
  • SyntheticEvent is no longer stored in the event pool, so e.persit() will no longer take effect;

link up

v17 opens a new chapter in React's incremental upgrades (with a slight bluff)

17 onwards, allow different React versions on the same page. According to the official demo example, it is implemented based on the feature of lazy loading, and the usage is somewhat similar to the gameplay of SPA micro-applications. Personally, I don’t think this is black magic. If you don’t need to reload and expect a separate react version for a component, you should report an error or an error, like the following:
20220528181348

So by understanding the first two features, it really confirms the official sentence: 17 is only to pave the way for 18 and later versions, in order to make it easier for users to upgrade the version

React18 new features

Auto Bacthing

Batching is React's grouping of multiple state updates into a single re-render for better performance (less render times).
Before React 18, batched updates only happened in React event callbacks, and updates inside Promise, setTimeOut, native event callbacks, or any other events were not batched, for example 🌰:

 // 18以前: .
setTimeout(() => {
  setCount(c => c + 1);
  setFlag(f => !f);
  // render 2次
}, 1000);

// 18及以后: 
setTimeout(() => {
  setCount(c => c + 1);
  setFlag(f => !f);
  // render1次
}, 1000);

Bypassing Black Magic: flushSync

Custom rendering priority

When react16 exits asynchronous rendering, the concept of rendering priority is proposed, like: user input > animation > list display. When multiple rendering tasks arrive, it will render the high-priority task first.

But because this is an ideal idea, it is difficult for the program itself to judge what must be a high priority, because the user usage scenarios are too complicated; so in 18, this underlying capability was further opened, and several hooks were launched: startTransition, useTransition , useDeferredValue, etc. These hooks allow users to customize the rendering priority

For example, enter the search box, intuitively:
20220530095408

The following is the pseudo code, just watch the demo directly:

 import {startTransition} from 'react';
// 高优先级: 输入数据回显
setInputValue(input);

// 使用Transition 对低优先级的渲染进行标记
startTransition(() => {
  setQuery(input);
});

The official Liezi, I think it will be easier for users who are graphical. If you are interested, you can learn about it: <Official Example>

So the latest version of React divides state updates into two categories:

  • Urgent updates will act directly on user interactions such as typing, clicking, etc.
  • Transition updates transition the UI from one view to another

Through these hooks we can customize the rendering priority.

New entry mount API: createRoot

 // 18 以前:
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);

// 18 以后:
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container); // 
root.render(<App tab="home" />);

It is worth mentioning that 18 is also compatible with the old mounting method, but this usage cannot use the new features (the development environment will prompt), which is also part of the incremental upgrade

11.55.29

incremental upgrade

The official word: Technically speaking, concurrent rendering is a breakthrough upgrade. Because concurrent rendering is interruptible, the component will behave slightly differently when it is enabled, about 0.2%.

Therefore, in order for everyone to upgrade to 18 more smoothly, the official proposed 渐进式升级 to provide a StrictMode API. Nodes wrapped with this module will comply with strict mode, which helps:

  • Identify insecure lifecycles
  • Warning for using obsolete string ref API
  • Warning for using the deprecated findDOMNode method
  • Detect unexpected side effects
  • Detect outdated context API
  • Ensure reusable state

The following demo, Header and Footer will be rendered in normal mode, while the Component node wrapped in StrictMode will be rendered in strict mode

 import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

Strict mode cannot automatically detect the side effects of your application version upgrade, it can only help to find them and make them more deterministic by deliberately repeatedly calling some declared functions (please check the official documentation for details)

 // 正常模式
* React mounts the component.
  * Layout effects are created.
  * Effects are created.

// 严格模式
* React mounts the component.
    * Layout effects are created.
    * Effect effects are created.
* React simulates effects being destroyed on a mounted component.
    * Layout effects are destroyed.
    * Effects are destroyed.
* React simulates effects being re-created on a mounted component.
    * Layout effects are created
    * Effect setup code runs

Although this module is only valid in the development environment, careful people will find that repeated destruction and mounting will bring new problems, such as:

 const [value, setValue] = useState(0);
useEffect(() => {
  setValue(val => val + 1);
})
// 正常模式打印的是1,但严格模式这会打印2;

There have been articles discussing this issue in China, and there is also an issue in the react repository to discuss this issue. If you are interested, you can click here .

Analysis of concurrent rendering

First, before talking about react rendering, review a knowledge point: js execution and UI rendering in the browser occur sequentially in a thread (including js execution, event response, timer, UI rendering), and the execution of js is single-threaded (based on eventloop).

20220603155838

This single thread is decided, processing A cannot handle B.

With this consensus, let's take a look at the rendering history of react

Synchronized rendering

The earliest react (before 16) is synchronous, which means that when the user triggers an update through setState, and the update is rendered to the page, it will go through two processes:

  • Diff stage: the root node will start diff, and find the difference between the DOM tree before and after the update;
  • Commit stage: According to the result of diff, update the UI to the page;

Since the whole process is synchronous, it will always occupy the js thread; therefore, during an update process, interactive events such as clicks and inputs on the page will wait until the update is completed, which is obviously a bad experience.

Asynchronous rendering

In order to solve the problem of synchronous rendering blocking the main thread, then make rendering more flexible - the biggest problem is not performance, but scheduling (React Conf 2018).

Based on the birth of a sensational term in the front-end circle Fiber , the biggest feature of the new rendering architecture is that it divides the previous one-way-to-black gameplay into two stages:

  • render phase: a task chain with a linked list structure, which can be interrupted;
  • Commit stage: is the process of updating the UI to the interface, which is synchronous and uninterrupted;

The relationship between the nodes in the render stage is represented by the linked list, and the method of time slicing is added. Whether the nodes on the linked list continue to compare backwards depends on whether the current thread is idle; and react will mark each update task with a priority, if the new If the update priority is higher than the task being processed, the previous task will be interrupted and discarded to process the higher priority task;

What needs to be understood here is that once an update task is interrupted and discarded, after the high-priority task is executed, the task needs to be calculated again from scratch.

Another point to remember is that there are Fibers and then hooks, not hooks that bring Fibers.

Concurrent rendering

As long as you have read some articles on React18, you may have heard of Concurrent Mode, Concurrent React or Concurrent features, these terms are not important, the important thing is to understand his purpose.

First of all, let's correct a wrong assumption that everyone may hear about asynchronous rendering: asynchronous rendering does not mean that two or more branches of a tree are rendered at the same time.

Move your toes and think about it, how is this possible, which itself is contrary to the principle of browser rendering.

Official original words:

Concurrency is not a feature, per se. It's a new behind-the-scenes mechanism that enables React to prepare multiple versions of your UI at the same time.

multiple versions of your UI circle it, the exam is to be taken.

Concurrent rendering successfully solves the problem of interruption and abandonment in asynchronous rendering, which can be resumed after interruption; however, in some scenarios, there will also be a problem of interruption and abandonment.

This ability can also unlock another usage scenario in the future: state reuse. For example, a tab switch, when switching from a to b, and then switching back to a from b, at this time, through some implementations, we can reuse the state and quickly display a on the screen;

The significance of concurrent rendering is far more than this (including the server and native side), I only picked up a few points that I can understand and share with you. Anyway, the official writing is very good, I personally still look forward to it.

Recommended reading:

Summarize

Through the familiarity with the new features of react18 and the explanation of the rendering mode, we can feel that this version will bring a visible improvement to the experience of our application, provided that you do not abuse it and use it.

And with the continuous exposure based on the bottom layer and the continuous construction of the concurrent mode, we may not use react, but Remix, Next, an ecological framework based on the react library, which is also the meaning of the establishment of the React working group. One, better build the React ecosystem.

It's hard to imagine that this is actually my first article in 2022. The most confusing thing in China this year is the Chinese economy, the second may be me, I hope this is a turning point! ! !

20220603161837


前端黑洞
生命不息,奋斗不止

不要假装很努力,因为结果不会陪你演戏

3.4k 声望
4.7k 粉丝
0 条评论
推荐阅读
6s到1s: 双端应用的秒开优化之路
近来,我们团队开始尝试用新的解决方案(双端开发,同时投放PC端和移动端)解决前端资源短缺问题。但提测后,测试提出我们移动端页面首屏太慢(6s+),体验极差。

前端黑洞2阅读 794

封面图
ESlint + Stylelint + VSCode自动格式化代码(2023)
安装插件 ESLint,然后 File -&gt; Preference-&gt; Settings(如果装了中文插件包应该是 文件 -&gt; 选项 -&gt; 设置),搜索 eslint,点击 Edit in setting.json

谭光志34阅读 20.9k评论 9

安全地在前后端之间传输数据 - 「3」真的安全吗?
在「2」注册和登录示例中,我们通过非对称加密算法实现了浏览器和 Web 服务器之间的安全传输。看起来一切都很美好,但是危险就在哪里,有些人发现了,有些人嗅到了,更多人却浑然不知。就像是给门上了把好锁,还...

边城32阅读 7.4k评论 5

封面图
涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果:这个确实有点意思,但是这是 CSS 能够完成的?没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们...

chokcoco24阅读 2.3k评论 3

在前端使用 JS 进行分类汇总
最近遇到一些同学在问 JS 中进行数据统计的问题。虽然数据统计一般会在数据库中进行,但是后端遇到需要使用程序来进行统计的情况也非常多。.NET 就为了对内存数据和数据库数据进行统一地数据处理,发明了 LINQ (L...

边城17阅读 2.1k

封面图
过滤/筛选树节点
又是树,是我跟树杠上了吗?—— 不,是树的问题太多了!🔗 相关文章推荐:使用递归遍历并转换树形数据(以 TypeScript 为例)从列表生成树 (JavaScript/TypeScript) 过滤和筛选是一个意思,都是 filter。对于列表来...

边城18阅读 7.9k评论 3

封面图
Vue2 导出excel
2020-07-15更新 excel导出安装 {代码...} src文件夹下新建一个libs文件夹,新建一个excel.js {代码...} vue页面中使用 {代码...} ===========================以下为早期的文章今天在开发的过程中需要做一个Vue的...

原谅我一生不羁放歌搞文艺14阅读 20.1k评论 9

不要假装很努力,因为结果不会陪你演戏

3.4k 声望
4.7k 粉丝
宣传栏