带有 Rails6 / Webpacker 的独立 React 组件

问题描述

我想知道如何/[接受的方式] 使用 webpacker 将独立的 React 组件添加到 rails 中的特定页面。用例是我有一个 Rails6 应用程序,我打算将 Rails 功能用于视图,而不是完整的 React SPA。但是,我想在特定 rails 视图中使用特定的自定义反应组件。该应用已安装并配置了用于响应的 webpacker。

我的问题:

  1. react-rails 是否适合这种用法?我曾尝试使用它,它确实完美地填充了用例,但我想知道是否可以在不添加此 gem 的情况下完成它,因为它似乎 webpacker 本身具有反应支持
  2. 是否要求 webpacker <%= javascript_pack_tag => 应该始终进入应用程序布局(head 标记),并像示例所说的那样动态地将包渲染到正文的末尾(appendChild)?我宁愿在视图中包含 pack 标签,并将其直接呈现到我指定的 div 中。 (下面的代码
  3. 如何将反应道具发送到由 <%= javascript_pack_tag => 呈现的独立反应组件?是否必须编写组件以获取挂载时所需的任何数据?

我尝试过的事情:

  1. 我查看了 webpacker 的文档,使用关键字“standalone”和“react”找到了很多问题,但没有找到任何问题。
  2. 下面的示例项目:它有效..但我不确定这是否是正确的方法,我不确定如何解决上面的问题 3(关于传递道具)

初始化

rails new petstore --webpack=react
bin/rails generate scaffold Pet pet_type:string pet_name:string
bin/rails db:migrate

package.json

{
  "name": "petstore","private": true,"dependencies": {
    "@babel/preset-react": "^7.12.10","@rails/actioncable": "^6.0.0","@rails/activestorage": "^6.0.0","@rails/ujs": "^6.0.0","@rails/webpacker": "5.2.1","babel-plugin-transform-react-remove-prop-types": "^0.4.24","prop-types": "^15.7.2","react": "^17.0.1","react-dom": "^17.0.1","turbolinks": "^5.2.0"
  },"version": "0.1.0","devDependencies": {
    "webpack-dev-server": "^3.11.2"
  }
}

config/webpacker.yml

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  webpack_compile_output: true

  # Additional paths webpack should lookup modules
  # ['app/assets','engine/foo/app/assets']
  additional_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .jsx
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

app/javascript/components/PetAnimation.js

import React from "react";
import PropTypes from "prop-types"

class PetAnimation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      petType: props.petType,};
  }

  render() {
    return (
      <div>Cute Pet Animation based on Pet Type and other imported libraries</div>
    )
  }
}

PetAnimation.propTypes = {
  petType: PropTypes.string
};

export default PetAnimation;

app/javascript/packs/pet_animation.js

import React from 'react'
import ReactDOM from 'react-dom'
import PetAnimation from "../components/PetAnimation";

document.addEventListener('DOMContentLoaded',() => {
  const rootElement = document.getElementById("pet-animation");
  if (rootElement != null) {
    ReactDOM.render(<PetAnimation/>,rootElement)
  }
})

app/views/pets/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Pet type:</strong>
  <%= @pet.pet_type %>
</p>

<p>
  <strong>Pet name:</strong>
  <%= @pet.pet_name %>
</p>

<p>
  <%= javascript_pack_tag 'pet_animation','data-turbolinks-track': 'reload' %>
  <div id="pet-animation"></div>
</p>
<%= link_to 'Edit',edit_pet_path(@pet) %> |
<%= link_to 'Back',pets_path %>

...它有效,有点:

petstore_show

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)