Blog

React 组件渲染优化

Cover Image for React 组件渲染优化
ZD
ZD

如何确定按钮被重新渲染了? 直观的颜色表示重新渲染了。

函数式组件版本

// The type of the props
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>

// A memoized button with a random background colour
const randomColor = () => Math.round(Math.random() * 255)
const Button = React.memo((props: ButtonProps) => (
  <button
    type="button"
    onClick={props.onClick}
    style={{
      border: '1px solid #ccc',
      borderRadius: '3px',
      padding: '10px',
      marginRight: '5px',
      background: `rgb(${randomColor()}, ${randomColor()}, ${randomColor()})`,
    }}
  >
    {props.children}
  </button>
))

PureComponent 版本

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>

class Button extends React.Component<ButtonProps, {}> {
  static randomColor() {
    return Math.round(Math.random() * 255)
  }

  shouldComponentUpdate(nextProps: ColorButtonProps, nextState: any) {
    const { onClick } = this.props
    if (onClick !== nextProps.onClick) {
      return true
    }
    return false
  }

  render() {
    const { onClick, children } = this.props
    return (
      <button
        type="button"
        onClick={onClick}
        style={{
          border: '1px solid #ccc',
          borderRadius: '3px',
          padding: '10px',
          marginRight: '5px',
          background: `rgb(${ColorButton.randomColor()}, ${ColorButton.randomColor()}, ${ColorButton.randomColor()})`,
        }}
      >
        {children}
      </button>
    )
  }
}

使用 useCallback 缓存状态修改函数

import React, { useState, useCallback } from 'react'

// Keeps track of all created functions during the app's life
const functions: Set<any> = new Set()

function App() {
  const [delta, setDelta] = useState(1)
  const [c, setC] = useState(0)

  const incrementDelta = useCallback(() => setDelta((delta0) => delta0 + 1), [])
  const increment = useCallback(() => setC((c0) => c0 + delta), [delta])

  // Register the functions so we can count them
  functions.add(incrementDelta)
  functions.add(increment)

  return (
    <>
      <div>
        <div> Delta is {delta} </div>
        <div> Counter is {c} </div>
        <br />
        <div>
          <ColorButton onClick={incrementDelta}>Increment Delta</ColorButton>
          <ColorButton onClick={increment}>Increment Counter</ColorButton>
        </div>
        <br />
        <div> Newly Created Functions: {functions.size - 2} </div>
      </div>
      <Switch>
        <Route path="/" exact component={withBasicLayout(Home)} />
        <Route path="/history" component={withBasicLayout(History)} />
        <Route path="/lock" component={LockScreen} />
      </Switch>
    </>
  )
}

export default App

遗留问题

React.StrictMode 导致 memo 无效

参考

  1. React’s useCallback and useMemo Hooks By Example