React hydrateRoot如何实现

React 服务器渲染中,hydrateRoot 是核心,它将服务器段的渲染与客户端的交互绑定在一起,我们知道 React 中 Fiber Tree 是渲染的的核心,那么 React 是怎么实现 hydrateRoot 的呢?首先我们验证一下,hydrateRoot 和 createRoot 有什么区别。分别创建两个 React 组件,一个用 createRoot,一个用 hydrateRoot,为了演示方便,直接用引入 React 脚本的方式。

CreateRoot

本例中,页面 Dom已经存在了一个 Button 按钮,createRoot 会将其替换掉而不会重用。直接替换 Root 节点,从 Console 中可以看到返回为 false,节点不同。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>
  <body>
    <div id="root"><button>0</button></div>
    <script type="text/babel">
      const useState = React.useState;

      function App() {
        const [state, setState] = useState(0);
        return (
          <button onClick={() => setState((state) => state + 1)}>
            {state}
          </button>
        );
      }

      const rootElement = document.getElementById("root");
      const originalButton = rootElement.firstChild;
      ReactDOM.createRoot(rootElement).render(<App />);
      setTimeout(
        () =>
          console.log(
            originalButton === rootElement.firstChild
            
          ),
        0
      );

    
    </script>
  </body>
</html>

在这里插入图片描述

hydrateRoot

修改代码 ReactDOM.createRoot(rootElement).render(); 到 ReactDOM.hydrateRoot(rootElement, ); ,代码只需要修改这一句,从截图中可以看到,D 节点没有被替换。
在这里插入图片描述
通过这个例子,可以看到 createRoot 和 hydrateRoot 的区别是在于是否替换节点,React 在渲染流程做了某些从而最终达到这种效果,我们看一下 React 的代码是怎么实现的。

在 React 中 Fiber 树的遍历通过 beginWork 和 completeWork 进行的,首先看 beginWork,beginWork 当 React 遇到 HostComponent HTML 节点时,进入 updateHostComponent,updateDateHOstComponent 会调用

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
tryHydrate 是核心代码,fiber 设置了 stateNode,stateNode 是 fiber 对应的 DOM Node,至此,beginWork 的逻辑结束了。
在这里插入图片描述

completeWork

现在我们来看,completeWork 方法中如何处理 hydrateRoot, 首先调用 popHydrationState,然后调用 prepareToHydrateHostInstance,最后调用 markUpdate,在 commit 阶段更新 DOM。

在这里插入图片描述
在这里插入图片描述
通过 updateFiber 更新节点数据。
在这里插入图片描述

总结

hydrateRoot 整体流程是:beginWork 创建节点,completeWork 完成并更新。这个设计还是很巧妙的,将显示和交互分离。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值