Дочерние элементы React parent pass будут запускать повторную передачу без изменения состояния / реквизита

#reactjs #react-hooks #rerender

#reactjs #реагирующие крючки #повторный рендеринг

Вопрос:

Когда у меня есть несколько дочерних элементов (HTML dom) в качестве реквизита для дочернего компонента и элемента управления в родительском, я обнаружил, что это вызовет повторный запуск!

Почему дочерние элементы React parent pass запускают повторный запуск без изменения состояния / реквизитов?

Как этого избежать? Проверьте следующее.

 
const InsideChild = React.memo(({children}) => {
  const countRef = useRef(0)
  countRef.current  = 1

  return (
    <div>render count: {countRef.current} {children}</div>
  )
})
                        
const OutsideParent = () => {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count   1)}>
        Click me
      </button>
      <div>
        Test1:
        <InsideChild />
      </div>
      <div>
         Test2:
         <InsideChild>
           <p>children as html dom will not trigger rerender.</p>
         </InsideChild>
      </div>
    </div>
  )
}

 

в качестве примера кода Test1 не будет запускать повторный запуск, а Test2 будет. Возможно ли этого избежать?

Более подробная информация и рабочий образец здесь:

https://codepen.io/sky790312/pen/QWqygxQ

Комментарии:

1. Запомните это: reactjs.org/docs/react-api.html#reactmemo

Ответ №1:

React.memo Не работает, когда вы отправляете html, потому что в этом случае дочерние элементы являются объектом, единственный способ сравнить его — это глубокое сравнение или что-то в этом роде.

Вы можете добавить функцию сравнения в свою заметку и сравнить внутренние реквизиты объектов в случае отправки html.

В примере я просто проверяю, являются ли реквизиты объектом, а затем сравниваю объект внутри, надеюсь, это поможет вам

 const comparisonFn = (prevProps, nextProps) => { 
  if(typeof prevProps?.children === 'object') {
    return prevProps?.children.props.children == 
      nextProps?.children.props.children
  } else {
    return prevProps?.children === nextProps?.children;
  }
}

const InsideChild = React.memo(({children}) => {
  const countRef = useRef(0)
  countRef.current  = 1

  return (
    <div>render count: {countRef.current} {children}</div>
  )
}, comparisonFn)
 

Комментарии:

1. Понял, теперь я знаю, что произойдет. Спасибо. Я редко вижу, чтобы проект обрабатывался подобным образом, должен ли я справиться с этим?