【问题标题】:In Rails how do I access a server-side rendered React component as HTML在 Rails 中,如何将服务器端呈现的 React 组件作为 HTML 访问
【发布时间】:2021-02-03 14:50:34
【问题描述】:

上下文

我正在尝试将 React 组件转换为 PNG,以便可以将其附加到 Rails 邮件程序中的电子邮件。该组件是一个馅饼Rechart

我想在 Rails 中完成这一切,而不是使用 Node.js 服务器解决方案,它使用 repng 之类的东西将组件转换为 PNG。

Rechart 将图表组件加载为 SVG,因此我可以访问 SVG 并使用 Mini-Magic 之类的东西将其转换为 PNG。

问题

如何在服务器端将 React 组件加载为 HTML 以便访问 SVG 进行转换。

要在 Rails 中服务器端加载组件,我们可以这样做 what react-rails suggests:

在视图中

<%= react_component('HelloMessage', {name: 'John'}, {prerender: true}) %>

或在控制器中

class TodoController < ApplicationController
  def index
    @todos = Todo.all
    render component: 'TodoList', props: { todos: @todos }, tag: 'span', class: 'todo'
  end
end

我想做类似this posts suggests 使用ReactDOMServer 的事情。

// Renders our Hello component into an HTML string
const html = ReactDOMServer.renderToString(<Hello />);

我需要在 Rails 邮件程序中使用 Ruby 进行等效操作。如何以 HTML 格式访问服务器端呈现的组件?

编辑:

sig 的回答是正确的,因为它允许您访问控制器实例的 HTML,这对我有用:

controller_instance = ComponentsController.new()
html_string = controller_instance.render_to_string(:action => "index", :layout => false)

但是,html_string 的输出是:

"<div data-react-class=\"personnel/TrainingStatusChart\" data-react-props=\"{&quot;metaData&quot;:{&quot;currentPage&quot;:1,&quot;scopedCount&quot;:23,&quot;statusGreyCount&quot;:15,&quot;statusHighCount&quot;:5,&quot;statusLowCount&quot;:2,&quot;statusMediumCount&quot;:1,&quot;totalCount&quot;:23,&quot;totalPages&quot;:1,&quot;unscopedCount&quot;:23},&quot;prerender&quot;:true}\"></div>\n"

它是 React 组件,其中包含所有道具。预渲染 React 组件不会在服务器端将其编译成 HTML。因此,无法访问 React 组件中的 SVG 以转换为 PNG。 This article 表示如下:

此预呈现过程无权访问窗口或文档,因此它不会加载运行时 JavaScript 或 CSS。

我仍然坚信这一定是可能的。也许以某种方式使用 Capybara 和 Headless Chrome 来呈现 React 组件。但是,我还没有找到一个示例实现。

【问题讨论】:

  • 它没有渲染整个组件的原因是因为react_component()实际上并没有在服务器上渲染组件(因为它没有做SSR)。 react_component() 仅在服务器上呈现最少的必要元素,以便它可以在客户端呈现组件。抱歉,如果这很明显,但只是想确保每个人都在同一页面上。

标签: javascript ruby-on-rails reactjs ruby recharts


【解决方案1】:

你可以尝试使用render_to_string控制器的方法:

controller_instance = ActionController::Base.new()  
#or
controller_instance = ApplicationController.new()

html_string = controller_instance.render_to_string template: 'path_to_file'

它接受与render 相同的参数。更多信息https://apidock.com/rails/ActionController/Base/render_to_string

【讨论】:

    猜你喜欢
    • 2015-09-08
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多