如果单个挂钩状态发生更改,则自定义挂钩返回组件将释放所有子代

时间:2020-04-30 15:07:04

标签: reactjs react-native react-hooks

为什么使用自定义钩子渲染组件会重新渲染App组件。如果我切换<Comp> or <AnotherComp>,则整个App组件将与其他组件一样重新呈现。

我尝试了React.memo并将组件再次包装在App组件中,但是没有效果。

我读到它的反应方式比较并认为函数是不同的渲染器。但是人们是否为此目的使用了高级模式?

export const useCard = (params)=>{
const { ToBeWrappedComponent } = params;
const [isOpen,setIsOpen] = useState(true);

const toggle= ()=> setIsOpen(!isOpen);

const WrappedComponent = ()=>{ 
return (
<Collapse isOpen={isOpen} >
<button onClick= {toggle}> </button>
<ToBeWrappedComponent />
</Collapse>
)
}

return [WrappedComponent,toggle]
};



const App = ()=>{
const [Comp, toggleComp] = useCard({ToBeWrappedComponent: ()=> (<h1>Wrapped Item <h1>) });
const [AnotherComp, toggleAnotherComp] = useCard({ToBeWrappedComponent: ()=> (<h1>Another Wrapped Item <h1>) })

return (
<AnotherComp > </AnotherComp>
<Comp> </Comp>
)
}

请注意,这段代码只是我创建的一个示例,用来说明我所面临的问题,我使用此方法进行了更复杂的操作,并且只想了解实现它的高级模式及其渲染的原因。谢谢

1 个答案:

答案 0 :(得分:1)

实际上是在App组件的函数中调用了useState的调用:

const [isOpen,setIsOpen] = useState(true);

因此它成为App状态的一部分,而不是包装组件状态的一部分。

组件会重新渲染,因为每次重新渲染App时,都会重新创建WrappedComponent函数。它是具有不同地址的不同功能,因此从头重新渲染了组件树。

这是您正在使用的一种非常奇怪的模式。您真的使事情复杂化了。为什么不简单地将render函数传递给包装器组件?

const TogglableComponent = ({ renderWrappedComponent, isOpen, onClick }) => { 
  return (
    <Collapse isOpen={isOpen} >
      <button onClick={onClick} />
      { renderWrappedComponent() }
    </Collapse>
  )
};

然后,您可以通过道具从其父级控制每个组件的切换状态。或者,如果您不在乎将切换状态传递给父组件,只需将其存储在包装器中即可:

const TogglableComponent = ({ renderWrappedComponent }) => {
  const [isOpen, setIsOpen] = React.useState(false);
  return (
    <Collapse isOpen={isOpen} >
      <button onClick={() => setIsOpen(!isOpen)} />
      { renderWrappedComponent() }
    </Collapse>
  )
};