12

是否可以在 Next.js中强制执行仅 SSR模式并仅部分水合页面?假设我有这个应用程序:

组件/dynamic.jsx

export default () => (
  <button onClick={() => console.log("I have been clicked")}>Click me</button>
)

页面/index.jsx

import DynamicComponent from "../components/dynamic.jsx";

export default () => (
  <div>
    <h1>Hello World</h1>
    <p>Lorem ipsum</p>
    <Hydrate>
      <DynamicComponent />
    </Hydrate>
  </div>
);

现在假设我们正在渲染pages/index.jsxNext.js因此它将在服务器上渲染并在客户端完全水合。出于性能原因(缩小包大小,减少执行时间)并让应用程序与广告()一起玩得更好,我只想DynamicComponent在客户端上水合,最好只将 JavaScript 加载DynamicComponent到客户端。

这可能吗

  • 反应?
  • Next.js?

谢谢

4

1 回答 1

11

您可以使用 hack 来做到这一点:

<>
  <StaticContent>
    <h1>Hello World</h1>
    <p>Lorem ipsum</p>
  </StaticContent>
  <DynamicComponent />
</>

StaticContent组件:

import { createElement, useRef, useState, useEffect } from 'react'

function useStaticContent() {
  const ref = useRef(null)
  const [render, setRender] = useState(typeof window === 'undefined')

  useEffect(() => {
    // check if the innerHTML is empty as client side navigation
    // need to render the component without server-side backup
    const isEmpty = ref.current.innerHTML === ''
    if (isEmpty) {
      setRender(true)
    }
  }, [])

  return [render, ref]
}

export default function StaticContent({ children, element = 'div', ...props }) {
  const [render, ref] = useStaticContent()

  // if we're in the server or a spa navigation, just render it
  if (render) {
    return createElement(element, {
      ...props,
      children,
    })
  }

  // avoid re-render on the client
  return createElement(element, {
    ...props,
    ref,
    suppressHydrationWarning: true,
    dangerouslySetInnerHTML: { __html: '' },
  })
}
``
于 2020-02-23T19:08:44.803 回答