React parent pass children 将触发重新渲染而不更改 state/props

Posted

技术标签:

【中文标题】React parent pass children 将触发重新渲染而不更改 state/props【英文标题】:React parent pass children will trigger rerender without state/props change 【发布时间】:2022-01-11 19:06:29 【问题描述】:

当我有一些子组件(html dom)作为子组件的道具并在父组件中控制时,我发现这会触发重新渲染!

为什么 React parent pass children 会在没有 state/props 改变的情况下触发重新渲染?

如何避免?检查以下内容。


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

【问题讨论】:

记住它: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)

【讨论】:

知道了,我知道现在发生了什么。谢谢。我很少看到这样的项目句柄,我应该处理吗?

以上是关于React parent pass children 将触发重新渲染而不更改 state/props的主要内容,如果未能解决你的问题,请参考以下文章

React类型检查

React.Children

深度对象路由的 Web API 最佳实践

11. react 组合与继承

11. react 组合与继承

基于react16.8创建自己的react