admin管理员组

文章数量:1424459

I am trying to figure out why when I click on a specific ponent its sibling it will render too

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} />
    </>
  )
}

I use useCallback and I pass theses function to use avoid that in any render the functions reference will be a different reference.

I am trying to figure out why when I click on a specific ponent its sibling it will render too

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} />
    </>
  )
}

I use useCallback and I pass theses function to use avoid that in any render the functions reference will be a different reference.

Share Improve this question asked Feb 21, 2021 at 19:22 Ismael RodriguezIsmael Rodriguez 3394 silver badges10 bronze badges 2
  • Because you pass in count1 / count2 as a prop as well. This props is changed so the ponent is re-rendered – Kevin Commented Feb 21, 2021 at 19:26
  • If DualCounter is re-renders, it's children will render too.. You can use memo – lissettdm Commented Feb 21, 2021 at 19:29
Add a ment  | 

1 Answer 1

Reset to default 5

You are seeing a re-render on the sibling <CountButton /> ponent, because each time you hit the button to update the counter, you are actually updating a state value in the parent ponent <DualCounter />, which causes a re-render on that ponent as well.

And since DualCounter is re-rendered, child ponents will re-render as well, which in this case includes both <CountButton /> elements.

A solution to prevent this, would be wrapping CountButton ponent with React.memo(). This will prevent a re-render on a ponent that didn't have any change on the props values.

Example below:

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} />
    </>
  )

Another solution would be not updating the DualCounter state on each change caused by events on your CountButton ponents, which will stop triggering unwanted re-renders on their siblings. You could handle the state directly on each CountButton ponent if this made sense for your app.

Alternatively, you could use a React state management tool, such as Redux, which also solves exactly this issue, by taking charge of delegating the state of your app separated from your ponents themselves.

本文标签: javascriptAvoid rerender with useCallbackStack Overflow