我正在使用react-static生成一个静态网站。使用the new hook 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的业务)。
React强烈禁止使用条件钩子,但是在非常的特定情况下,做类似这样的事情是没有道理的:
if(typeof window !== 'undefined')
useLayoutEffect(() => {
document.body.style.overflowY = loading ? 'hidden' : 'visible'
},
[loading]
)
正确的方法是什么?
答案 0 :(得分:0)
我认为您应该使用上下文将值“隐藏/可见”传递给其他组件。在这种情况下,呈现所有页面包装的组件。
useEffect(() => {
fnSetContextValue(isLoading ? 'hidden' : 'visible')
}, [isLoading]);
您还可以尝试使用requestAnimationFrame函数而不是上下文:
useEffect(() => {
window.requestAnimationFrame(() => {
document.body.style.overflowY = loading ? 'hidden' : 'visible';
});
}, [isLoading]);
答案 1 :(得分:0)
好的,这是我想出的不太脏解决方案。而不是实施幼稚的解决方案,即。有条件的钩子:
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
尽管要小心,但这只能起作用,因为我的布局效果不会影响React的DOM部分,这就是警告的全部内容。