呈现静态网站时的条件挂钩

时间:2019-03-05 10:23:03

标签: reactjs server-rendering react-static

我正在使用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]
  )

正确的方法是什么?

2 个答案:

答案 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部分,这就是警告的全部内容。