我是React的资深人士,但是我对在React 16中使用钩子和闭包还是比较陌生的,我发现有些根本上对我没有意义的事情。在我的应用程序中,我有无数个示例,其中当状态var发生变化时,UI会闪烁或重新布置所有内容,但是直到今天,当使用动画时,才可以明显看出它在定义我的Functional组件的范围内起作用。(如果相关,该应用程序将基于Next.js btw构建!)
考虑以下ExperienceBuilder
页面,该页面允许用户编辑文档。有一个可以打开和关闭的右侧菜单-可以动画显示。跟踪是否应显示菜单的状态由父级管理,但动画是使用RightMenuContainer
Component内部的Tailwind CSS处理的。当我在独立的范围内实现它们时,一切都将完美运行:
const RightMenuContainer = props => {
return (
<div className={props.isOpen ? '' :'transform translate-x-full -mr-90'}>
{/* ...buttons and stuff... */}
</div>
)
}
const ExperienceBuilder = props => {
[isOpen, setIsOpen] = useState(true)
return (
<>
<RightMenuContainer isOpen={isOpen} >
<Button onClick={() => setIsOpen(!isOpen)} title={isOpen ? "Show Menu" : "Hide Menu"} />
{/* ...other stuff in the main container... */}
</>
)
}
但是,一旦我将移到的RightMenuContainer
内部ExperienceBuilder
,它将停止工作!:
const ExperienceBuilder = props => {
[isOpen, setIsOpen] = useState(true)
const RightMenuContainer = props => {
return (
<div className={props.isOpen ? '' :'transform translate-x-full -mr-90'}>
{/* ...buttons and stuff... */}
</div>
)
}
return (
<>
<RightMenuContainer isOpen={isOpen} >
<Button onClick={() => setIsOpen(!isOpen)} title={isOpen ? "Show Menu" : "Hide Menu"} />
{/* ...other stuff in the main container... */}
</>
)
}
在这一点上,我意识到我应该以第一种方式实现事情,以免出现错误,但是了解WHY确实很有帮助。99%的时间,后一个示例可以正常工作,并且使子级对象在范围内的编码速度更快,因为我的子级组件可以读取父级状态,而无需将状态作为prop传入。我的希望是,如果我能了解引擎盖下发生的事情,那么我可以做出更好的设计决策,以决定何时值得把弯角和使组件纳入范围,以及何时不值得。
我尝试过的事情没有帮助:
React.memo
您的组件正在全部安装和卸载,如果添加,useEffect
您将看到:
const RightMenuContainer = props => {
useEffect(() => console.log('mount'),[]) // empty array only executes on mount
return (
<div className={props.isOpen ? '' :'transform translate-x-full -mr-90'}>
{/* ...buttons and stuff... */}
</div>
)
}
在每次重新ExperienceBuilder
渲染时,RightMenuContainer
都会创建一个新功能。由于动画仅在已安装组件的情况下发生,因此动画不起作用。
要解决此问题,在您的情况下,请使用useCallback包装函数,并使用另一个空数组[]
作为参数来记住您的函数:
const RightMenuContainer = React.useCallback(props => {
useEffect(()=>{console.log('mount')}, [])
return (
<div className={props.isOpen ? '' :'transform translate-x-full -mr-90'}>
{/* ...buttons and stuff... */}
</div>
)
},[])
这样它将记住您的功能组件,您可以检查它console.log('mount')
仅显示一次
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句