ReactDOM.hydrate() 会在客户端触发生命周期方法吗?

Will ReactDOM.hydrate() trigger lifecycle methods on the client?

React 16 docsReactDOM.hydrate(),

Same as render(), but is used to hydrate a container whose HTML contents were rendered by ReactDOMServer. React will attempt to attach event listeners to the existing markup.

  1. ReactDOM.hydrate() 是否也会在初始渲染期间触发客户端上的生命周期方法,例如 componentWillMount()componentDidMount()

  2. 水合时客户端会调用render()方法吗?我想不是,因为那是 ReactDOM.render()ReactDOM.hydrate() 之间的区别?

如果 render 方法不会在客户端调用,我们不会期望 componentDidMount() 生命周期方法被触发。

如果在客户端调用none个生命周期方法,我们怎么知道React什么时候完成渲染。我假设 callback 的语法如下:

ReactDOM.hydrate(element, container[, callback])

我想了解当 React "attempting to attach event listeners to existing markup".

时是否有可用的生命周期方法/挂钩(它们可以更好地控制应用程序)
  1. 因为 ReactDOM.hydrate 被(并且应该)在客户端调用然后 YES 它应该 运行 componentDidMountcomponentWillMount 在服务器上呈现时已被调用。 componentDidMount 不在服务器上 运行,因此当您调用 hydrate 时,应用 运行 是事件。

  2. 将 hydrate 视为另一种渲染方法。它确实呈现但不以相同的方式呈现。它会查找服务器呈现的 React 和客户端 React 之间的不匹配。它不会再次渲染所有内容。

React expects that the rendered content is identical between the server and the client. It can patch up differences in text content (such as timestamps), but you should treat mismatches as bugs and fix them

然而,您可能想要做一些疯狂的事情,比如在客户端呈现完全不同的东西(与在服务器端呈现的东西)。为此请注意这段

If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.

如您所见,它进行了渲染过程。如果没有不匹配,React 会为此进行优化。

我希望它能说明问题。我根据使用 React SSR 的经验和阅读文档的基本理解来发言。

渲染的元素在服务器和客户端之间可能不相同,因为最初元素在内存中的服务器上渲染成文本,因此它们没有挂载。当内容被移动到客户端时,它可以通过 hydrate 重新附加以做出反应,这是假的“渲染”以连接其余的反应功能,例如事件。

为了判断它何时补水,这里有一篇来自互联网的文章,我发现它清楚地说明了上述合理性。 https://dev.to/merri/understanding-react-ssr-spa-hydration-1hcf?signin=true

const HydrateContext = createContext('hydrated')

export function useIsHydrated() {
    return useContext(HydrateContext)
}

export function IsHydratedProvider({ children }) {
    const [isHydrated, setIsHydrated] = useState(false)
    useEffect(() => {
        setIsHydrated(true)
    }, [])
    return (
        <HydrateContext.Provider value={isHydrated}>
            {children}
        </HydrateContext.Provider>
    )
}

要使用它,

function MyComponent() {
    const isHydrated = useIsHydrated()
    return !isHydrated ? 'Initial render' : 'SPA mode'
}

function App() {
    return (
        <IsHydratedProvider>
            <MyComponent />
        </IsHydratedProvider>
    )
}

我的感觉是,任何渲染的组件都会从服务器传送到客户端。

p.s这里还有一篇文章讲的是挂载后的二次渲染,https://medium.com/swlh/how-to-use-useeffect-on-server-side-654932c51b13

我在 TypeScript 系统中读取了 ReactDOM.hydrate 的类型:

(
  element: SFCElement<any> | Array<SFCElement<any>>,
  container: Container| null,
  callback?: () => void
): void;

上述声明的示例:

ReactDOM.hydrate(
  <App />, // element
  document.getElementById('root'), // container
  () => { // callback

    /* do what you want after hydration */
  }
);