如何安全地传递参数以使组件与react-rails交互

时间:2019-01-24 17:35:18

标签: reactjs react-rails

我正在使用react-rails向Rails应用程序中的现有红宝石添加一些react组件。我刚刚意识到,如果您检查组件,则很容易看到最初传递给组件的所有道具

<%= react_component('ProfileWeeklyWriting', {
    languages: @user.languages,
    currentUser: @current_user,
    responses: @writing_responses,
    clapLottie: asset_url('lottie/clap.json'),
    clapIcon: asset_url('icons/clap.svg'),
    arrowIcon: asset_url('icons/arrow_green.png')
    }) %>

但是当您检查元素时,将显示所有这些变量!

enter image description here

我知道我可以从组件内部进行ajax调用,但是有一种方法可以在不将变量显示给世人的情况下将变量初始传递给组件?

1 个答案:

答案 0 :(得分:1)

让我们对它的工作原理进行一些探讨。当您在没有任何后端引擎的情况下执行经典SPA时,通常会执行

ReactDOM.render(<App />, document.getElementByID('root'))

仅将根组件呈现在<div id="root" />处。在顶部应用Rails模板时,您将连接2个不同的世界。 ReactDOM和Rails苗条的模板引擎(可能),但他们彼此之间一无所知。 ReactRails实际上只是例程,它会执行以下操作:

  • 1将自定义react-rails脚本注入页面
  • 等待DOM准备就绪
  • 收集所有[data-react-class]元素
  • 遍历它们并使用道具呼叫ReactDOM

您可以将其视为调用多个“小型应用程序”,但实际上它们只是组件(react不能区分应用程序/组件,它始终只是组件)

所以代码是这样的(我没有检查原始代码,但是我为公司编写了自己的react-rails实现)

  function init () {
    const elements = document.querySelectorAll('[data-react-class]')

    if (elements.length > 0) {
      Array.prototype.forEach.call(elements, node => {
        if (node) {
          mount(node)
        }
      })
    }
  }

  function mount(node) {
    const { reactClass, reactProps } = node.dataset 
    const props = JSON.parse(reactProps || '{}')
    const child = React.createElement(window[reactClass], props)
    ReactDOM.render(child, node)
  }

然后准备好DOM

document.addEventListener('DOMContentLoaded', e => {
  init()
})

事实上,Rails并不了解React,而React也不了解Rails,除非它不在window.上(这种方法被强烈反对。

在现实世界中,有多种方法可以进行“服务器”渲染,这意味着这部分代码是在服务器上完成的,以不暴露道具和整个React生命周期,而只是将实际准备好的HTML刷新到DOM。这意味着在生命周期中之前,HTML被发送到客户端,即所谓的transpiler,它会编译这些组件,您可以在此处阅读有关内容

  1. https://github.com/reactjs/react-rails#server-side-rendering

因此,它仅在https://github.com/rails/execjs的帮助下调用了这些方法

因此,如何不向客户端“展示”道具的唯一方法是通过某种引擎(在您的语言中使用某种JS实现或直接在node.js后端)在后端“预渲染”组件。希望我给您一个更好的画面,它如何工作以及如何解决!