避免使用“useCallback”重新渲染

Ism*_*uez 1 javascript reactjs react-hooks

我试图弄清楚为什么当我单击某个特定组件时,它的同级组件也会呈现

function CountButton({increment, count, number}) {
  console.log(`Render CountButton ${number}`)

  return <button onClick={() => increment(count + 1)}>{count}</button>
}

function DualCounter() {
  const [count1, setCount1] = React.useState(0)
  const increment1 = React.useCallback(() => setCount1(c => c + 1), [])
  const [count2, setCount2] = React.useState(0)
  const increment2 = React.useCallback(() => setCount2(c => c + 1), [])
  console.log('Render DualCounter')

  return (
    <>
      <CountButton count={count1} increment={increment1} number={1} />
      <CountButton count={count2} increment={increment2} number={2} />
    </>
  )
}
Run Code Online (Sandbox Code Playgroud)

我使用useCallback并传递这些函数来避免在任何渲染中函数引用将是不同的引用。

tmi*_*lar 5

您会看到同级组件上的重新渲染<CountButton />,因为每次点击按钮更新计数器时,您实际上是在更新父组件中的状态值<DualCounter />,这也会导致该组件上的重新渲染。

由于DualCounter重新渲染,子组件也将重新渲染,在本例中包括两个<CountButton />元素。

防止这种情况的解决方案是用React.memo()包装 CountButton 组件。这将防止在 props 值没有任何更改的组件上重新渲染。

下面的例子:

function CountButton({increment, count, number}) {
  console.log(`Render CountButton ${number}`)

  return <button onClick={() => increment(count + 1)}>{count}</button>
}

const CountButtonMemo = React.memo(CountButton)

function DualCounter() {
  const [count1, setCount1] = React.useState(0)
  const increment1 = React.useCallback(() => setCount1(c => c + 1), [])
  const [count2, setCount2] = React.useState(0)
  const increment2 = React.useCallback(() => setCount2(c => c + 1), [])
  console.log('Render DualCounter')

  return (
    <>
      <CountButtonMemo count={count1} increment={increment1} number={1} />
      <CountButtonMemo count={count2} increment={increment2} number={2} />
    </>
  )
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是不更新组件DualCounter上的事件引起的每个更改的状态CountButton,这将停止触发其同级组件上不需要的重新渲染。如果这对您的应用程序有意义,您可以直接在每个 CountButton 组件上处理状态。

或者,您可以使用 React 状态管理工具,例如Redux,它也可以通过负责委托与组件本身分离的应用程序状态来解决这个问题。