The React update mechanism is a batch update mechanism, which is further advanced by the hooks API. The advantage of batch updates is that there is no need to deal with update details, batch updates are much more efficient than directly manipulating DOM elements, and there are no performance bottlenecks in most scenarios. This is especially true when there are relatively few page elements on mobile.

On the PC side, however, larger screens and more complex interactions have led us to develop more react components to compose applications, and if you often use global data to render your pages, you can quickly run into performance bottlenecks.

The main reason is that while the virtual DOM avoids expensive DOM manipulation, the render function that creates the virtual DOM itself cannot be omitted, as in the following scenario

A list of multiple lines, each line being a separate component, in the render function we console.log(‘render’)

When we try to update the list, the usual thing to do is to reset the list with props, something like this

<Table data={arr}>
Copy the code

Update the internal row component by modifying the data in the ARR to trigger the update and rendering of the Table.

However, as I mentioned at the beginning, this mode is a batch update mode where only one row of data changes, but render is still triggered on all rows even if the DOM does not change.

You can see that the render of log has changed from 10 to 20 times. In real scenarios, the components in the Table row are often very complex, and some scenes need to render a large amount of data at the same time. Even if you use technologies like virtual scrolling and virtual nodes, It is also difficult to keep a batch of updates under 16ms, if more than 32ms then there will be significant lag.

When it comes to performance, you might think of the official recommended scheme React. Memo, unfortunately, doesn’t work for props of complex types either. In this example I tried to use React


const MemoCell = React.Memo(Cell)

Copy the code

For memo to work, you’d have to write your own comparison function, but even then, render is still triggered in scenarios like the useContext package, and maintaining the comparison function is an unnecessary overhead.

Is there any way to achieve a precise update like document.getelementById?

You might think of using refs, but maintaining the refs of internal elements in addition is another issue. In addition, manipulating the DOM directly through ref bypasses recat’s update mechanism. This is a hack, not a necessity.

React update mechanism how to find a non-batch update mode in react update mechanism to trigger the render of a component exactly?

Through practice we came up with a plan.

Use rx.js to establish bidirectional communication for each React component instance

Within Rdeco, we built a proxy component for each React component by leveraging the powerful subscription and push capabilities of rx.js. Component instances with the same name share the same proxy component. When the name is unique, the proxy component is also unique, so it is possible to use the proxy component to implement precise updates without unnecessarily rendering batch updates. To do this, You simply make the key part of the proxy component name.

The final code looks like this.

import "./styles.css";
import { createComponent, inject } from "rdeco";
import React, { useState } from "react";

const Cell = createComponent({
  name: "cell".state: {
    num: null
  },
  exports: {
    change(num) {
      this.setter.num(num); }},view: {
    render() {
      console.log("render");
      return (
        <div
          style={{
            margin: "12px",
            padding: "12px",
            border: "1px solid #000}} ">
          1{this.props.children}
          {this.state.num}
        </div>); }}});function createArray(num) {
  const arr = [];
  for (let index = 0; index < num; index++) {
    arr.push(index);
  }
  return arr;
}

const MemoCell = React.memo(Cell);

const Tabel = createComponent({
  name: "table".view: {
    render() {
      return (
        <div>
          {this.props.data.map((d) => {
            return (
              <MemoCell membrane={{ name: `cell-The ${d}` }} key={d}>
                {d}
              </MemoCell>
            );
          })}
        </div>); }}});export default function App() {
  const [arr, setArr] = useState(createArray(10));
  const onClick = () = > {
    setArr(
      arr.map((a) = > {
        returna; })); };const onAccurateClick = () = > {
    inject("cell-5").change(66);
  };
  return (
    <div className="App">
      <Tabel data={arr} />
      <button onClick={onClick}>Revise the content of item 15 extensively</button>
      <p />
      <button onClick={onAccurateClick}>Revise item 15 accurately</button>
    </div>
  );
}
Copy the code

The online dome: codesandbox. IO/s/wispy – daw… If you have React Dev Tools enabled, you can use the Hightlight Render option to compare the updates between the two buttons.

If you’re interested in these things, check out our project at 👏 github.com/kinop112365…

Also welcome to the comments section 😄