尝试在 Umbraco 的 HTML 原始 HTML 中水化 ReactJS.net SSR 组件

Stuck trying to hydrate ReactJS.net SSR components in raw HTML from Umbraco

我有一个 Umbraco CMS 松散地与 ReactJS.net 一起工作。我有一个根 <App> 组件,它采用(Umbraco 节点 ID 和路径)对象的数组 prop,用于使用 [= 为站点中的每个页面生成 <Route> 15=] 比赛。 <App>UmbracoViewPage 中呈现并在客户端浏览器中呈现良好 - 使用 @Html.ReactInitJavaScript(),它会按预期进行水合。

<Content> 组件使用 dangerouslySetInnerHTML 加载页面 HTML。我有一些自定义的 Umbraco 网格编辑器,它们不是在 ASP .NET 视图中生成常规标记,而是调用 @Html.React() 来呈现一个自定义 React 组件,该组件可能需要 prop或两个。

在初始页面加载时,网格 HTML 是在服务器端生成的,这些嵌套组件在浏览器中工作正常,因为 ReactJS.net 正在为每个网格组件传递 ReactDOM.hydrate() 调用(由 @Html.ReactInitJavaScript() 触发)。

但是一旦前端路由发生变化,<App> 就会根据路径安装相关的 <Content> 组件,这会调用带有 Umbraco 节点 ID 的 Umbraco SurfaceController .使用 dangerouslySetInnerHTML.

返回并加载该节点的页面网格 HTML

问题是我现在有原始 HTML,其中包括多个需要补水的 React 组件。因为它是在浏览器中加载的,所以不再有 @Html.ReactInitJavaScript() 调用分别对所有组件进行补水。

我怎样才能做到这一点?

注意:回答我自己的问题,以防它对正在使用 Umbraco 和 React 并希望实现更紧密集成的任何人有所帮助。

TL;DR - 在我的内容 API 响应中包含组件名称、React ID 和 props 的列表,允许我的前端代码以大致相同的方式处理它正如 ReactJS.NET 的 @Html.ReactInitJavaScript 助手所做的那样(我认为)。

我的解决方案是修改我的 SurfaceController 以包含标记中呈现的所有 React 组件的列表。所以它的作用与 ReactJS.NET 的 @Html.ReactInitJavaScript 助手非常相似,但在我的 SurfaceController API 方法中。

我扩展了 ReactJS.NET 的 @Html.React helper so that details about the component called are also added to a custom helper service I named ReactComponentHydrator (gist,每个请求单例)*。对于每个组件,我存储组件名称(例如 Component.ExampleComponent)、HTML 标记中包含的 React ID(例如 react_d1gC4eKqaUatZWfAdtjkTA)以及随它发送的道具。

据此,在前端代码中,我将创建 hydrate 每个组件,一旦 HTML 通过 dangerouslySetInnerHTML 加载。

*ReactJS.NET does seem to keep track of each component called 但这是内部的,不会通过我能找到的任何 API 公开。