9

React 16 文档中关于ReactDOM.hydrate()

与 render() 相同,但用于水合其 HTML 内容由 ReactDOMServer 渲染的容器。React 将尝试将事件侦听器附加到现有标记。

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

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

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

如果客户端没有调用任何生命周期方法,我们怎么知道 React 何时完成渲染。我想callback在以下语法中:

ReactDOM.hydra(元素,容器[,回调])

我想了解当 React “尝试将事件侦听器附加到现有标记”时是否有可用的生命周期方法/钩子(对应用程序提供更多控制)。

4

3 回答 3

15
  1. Since ReactDOM.hydrate is (and should be) called on the client then YES it is supposed to run componentDidMount. componentWillMount is already called when rendered on the server. componentDidMount does not run on the server, therefore when you call hydrate, the app runs the event.

  2. Think about hydrate as a different render method. It does render but not in the same way. It looks for mismatches between your server rendered React and your client React. It does not render everything again.

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

However you might want to do some crazy stuff like rendering something completely different on the client side (than what was rendered on the server). For this pay attention to this paragraph

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.

So as you can see it does a render pass. If there are no mismatches React is optimized for that.

I hope it was clarifying. I speak from experience with React SSR and basic understanding of reading the docs.

于 2017-11-13T13:53:03.523 回答
0

我阅读了ReactDOM.hydrateTypeScript 系统中的类型:

(
  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 */
  }
);
于 2021-10-13T09:48:24.940 回答
0

服务器和客户端之间渲染的元素可能不同,因为最初这些元素在服务器的内存中渲染为文本,因此它们没有被挂载。当内容被移动到客户端时,它可以被重新连接以做出反应,通过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>
    )
}

在我看来,任何渲染的组件都会从服务器传送到客户端。

ps 这是另一篇关于挂载后第二次渲染的文章,https://medium.com/swlh/how-to-use-useeffect-on-server-side-654932c51b13

于 2021-05-21T18:27:01.657 回答