React性能优化之unstable_batchedupdates(batch)用法详解

7,965 阅读1分钟

当在一个异步操作之后需要setState多次时,render函数会执行多次。

import React, {useState} from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function App() {
  const [num, setNum] = useState(1);
  const [str, setStr] = useState('a');
  const clickHandler = () => {
    setTimeout(() => { // 模拟异步
      setNum(2); // 这里触发的console.log('render')是没必要的
      setStr('c'); // 我们仅仅需要这里触发console.log('render')
    }, 1000);
  }

  console.log('render'); // 初始化时log一次,clickHandler触发后log两次。
  return (
    <div className="App">
      <h1 onClick={clickHandler}>
      	<span>{num}</span>
        <span>{str}</span>
      </h1>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
    <App />,
  rootElement
);

很显然我们仅仅需要第二次的render足以。

优化:

import React, {useState} from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function App() {
  const [num, setNum] = useState(1);
  const [str, setStr] = useState('a');
  const clickHandler = () => {
    setTimeout(() => { // 模拟异步
      ReactDOM.unstable_batchedUpdates(() => { // 仅仅加了unstable_batchedUpdates
        // 这里的两个setState会合并执行一次。
        setNum(2); 
        setStr('c');
      });
    }, 1000);
  }

  console.log('render'); // 初始化时log一次,clickHandler触发后log一次。
  return (
    <div className="App">
      <h1 onClick={clickHandler}>
      	<span>{num}</span>
        <span>{str}</span>
      </h1>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
    <App />,
  rootElement
);

注意事项:

setTimeout(() => { 
  let tmp = 1;
  ReactDOM.unstable_batchedUpdates(() => { //unstable_batchedUpdates 是一个同步操作
    setNum(2); 
    setStr('c');
    tmp = 3;
  });
  console.log(tmp) // 3
}, 1000);
const clickHandler = () => {
 // setTimeout(() => { // 如果setState之前没有异步操作,则不需要unstable_batchedUpdates
  //  ReactDOM.unstable_batchedUpdates(() => { 
      // 这里的两个setState也会合并执行一次,react内部会自动处理。
      // 但如果有异步,react无法侦测异步。所以需要自己加unstable_batchedUpdates。
      setNum(2); 
      setStr('c');
   // });
 // }, 1000);
}

如果有用react-redux可以用batch代替unstable_batchedUpdates。batch底层还是调用的unstable_batchedUpdates。

import { batch } from 'react-redux';
  1. 此文的方法对redux的dispatch同样生效。dispatch底层其实也是用setState触发组建更新。