我正在使用React static生成静态网站。使用新钩API中的useLayoutEffect
,我在静态渲染阶段(与服务器端渲染相同的API)中获取此警告:
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format.
This will lead to a mismatch between the initial, non-hydrated UI and th e intended UI.
To avoid this, useLayoutEffect should only be used in components that render exclusively on the client.
当然这是有道理的。但是,当人们确定不会有任何不匹配时,摆脱此警告的好选择是什么?
在我的布局效果中,我只在body
标签中添加了一些CSS,因此在客户端的水合阶段不会有任何不匹配(因为body
不是React的业务)。
使用有条件钩子反应强烈禁止,但是在此非常特定的情况下,做类似:
的事情是没有意义的。if(typeof window !== 'undefined')
useLayoutEffect(() => {
document.body.style.overflowY = loading ? 'hidden' : 'visible'
},
[loading]
)
正确的方法是什么?
我认为您应该使用上下文将"隐藏/可见"值传递给其他组件。在这种情况下,呈现所有页面包装器的组件。
useEffect(() => {
fnSetContextValue(isLoading ? 'hidden' : 'visible')
}, [isLoading]);
您还可以尝试使用requestAnimationFrame函数而不是上下文:
useEffect(() => {
window.requestAnimationFrame(() => {
document.body.style.overflowY = loading ? 'hidden' : 'visible';
});
}, [isLoading]);
好的,所以这是我想到的不是那么dirty 解决方案。而不是实施幼稚的解决方案,即。有条件的钩子:
const Layout = () => {
const [loading, setLoading] = useState()
if(typeof window !== 'undefined')
useLayoutEffect(() => {
document.body.style.overflowY = loading ? 'hidden' : 'visible'
}, [loading])
return ( ... )
}
export default Layout
在许多情况下,哪种感觉很脏,反图案,语义上的错误和无用(为什么要在每个渲染下检查window
?),我只是将条件放在组件外面:
const LayoutView = ({ loading, setLoading }) => ( ... )
const Layout = (typeof window === 'undefined') ? (
() => {
const [loading, setLoading] = useState()
return <LayoutView loading={loading} setLoading={setLoading}/>
}
): (
() => {
const [loading, setLoading] = useState()
useLayoutEffect(() => {
document.body.style.overflowY = loading ? 'hidden' : 'visible'
}, [loading])
return <LayoutView loading={loading} setLoading={setLoading}/>
}
)
export default Layout
请注意,这仅是因为我的布局效应不会影响DOM的React的一部分,这是警告的全部。