0

I want to implement a simple chat component written in react in rails 6 application. My idea is to put js link on another webpage on which my chat will be rendered. Basically, I follow gorails.com tutorial. Source code of it: link Just for test purpose, I was able to run and embed vue components widget from that tutorial on my local machine. However in my case, instead of vue.js, I use react js. I also replaced webpacker with shakapacker.

My problem is that my javascript code is not triggered on another page, chat component does not render - no console log output either. On website where I want to embed it, inside developer tab, I can see that my embedded script has been downloaded and there is no error.

Does someone has idea what could be wrong? what I have to adjust?

Below is my code:

embed.js

import React from 'react';
import { createRoot } from 'react-dom/client';
import Chat from '../components/chats/ChatsIndex';

const event = (typeof Turbolinks === 'object' && Turbolinks.supported) ? 'turbolinks:load' : 'DOMContentLoaded';
console.log("embeded code")

document.addEventListener(event, () => {
    const el = document.querySelector('#my-react-component');
    const root = createRoot(el);
    console.log("finding element")
    console.log(el)
    if (el) {
        console.log('found element)
        root.render(<Chat />);
    }
});

rails embeded controller:

class EmbedsController < ApplicationController
  include ActionView::Helpers::AssetUrlHelper
  include Shakapacker::Helper

  protect_from_forgery except: :show

  def show
    respond_to do |format|
      format.js  { redirect_to sources_from_manifest_entrypoints(["embed"], type: :javascript).first }
    end
  end
end

webpack config js

const { generateWebpackConfig } = require('shakapacker')
const webpackConfig = generateWebpackConfig()
webpackConfig.devtool = false
module.exports = webpackConfig

package.json

{
  "name": "app",
  "private": true,
  "dependencies": {
    "@babel/core": "7",
    "@babel/plugin-transform-runtime": "7",
    "@babel/preset-env": "7",
    "@babel/preset-react": "^7.18.6",
    "@babel/runtime": "7",
    "axios": "^1.2.2",
    "babel-loader": "8",
    "bootstrap": "4.4.1",
    "compression-webpack-plugin": "9",
    "css-loader": "^6.8.1",
    "css-minimizer-webpack-plugin": "^5.0.1",
    "prop-types": "^15.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react_ujs": "^2.6.2",
    "sass": "^1.64.1",
    "shakapacker": "7.0",
    "style-loader": "^3.3.3",
    "terser-webpack-plugin": "5",
    "webpack": "5",
    "webpack-assets-manifest": "5",
    "webpack-cli": "4",
    "webpack-dev-server": "^4.15.1",
    "webpack-merge": "5"
  },
  "version": "0.1.0",
  "babel": {
    "presets": [
      "./node_modules/shakapacker/package/babel/preset.js",
      "@babel/preset-react"
    ]
  },
  "browserslist": [
    "defaults"
  ],
  "devDependencies": {
    "mini-css-extract-plugin": "^2.7.6",
    "node-sass": "^9.0.0",
    "sass-loader": "^13.3.2"
  }
}

shakapacker config

# Note: You must restart bin/webpacker-dev-server for changes to take effect

default: &default
  source_path: app/javascript

  # You can have a subdirectory of the source_path, like 'packs' (recommended).
  # Alternatively, you can use '/' to use the whole source_path directory.
  source_entry_path: packs

  # If nested_entries is true, then we'll pick up subdirectories within the source_entry_path.
  # You cannot set this option to true if you set source_entry_path to '/'
  nested_entries: false

  public_root_path: public
  public_output_path: packs
  cache_path: tmp/shakapacker
  webpack_compile_output: true
  # See https://github.com/shakacode/shakapacker#deployment
  shakapacker_precompile: true

  # Location for manifest.json, defaults to {public_output_path}/manifest.json if unset
  # manifest_path: public/packs/manifest.json

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

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

  # Select loader to use, available options are 'babel' (default), 'swc' or 'esbuild'
  webpack_loader: 'babel'

  # Set to true to enable check for matching versions of shakapacker gem and NPM package - will raise an error if there is a mismatch or wildcard versioning is used
  ensure_consistent_versioning: false

  # Select whether the compiler will use SHA digest ('digest' option) or most most recent modified timestamp ('mtime') to determine freshness
  compiler_strategy: digest

development:
  <<: *default
  compile: false
  compiler_strategy: mtime

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3036
    # Hot Module Replacement updates modules while the application is running without a full reload
    hmr: false
    # If HMR is on, CSS will by inlined by delivering it as part of the script payload via style-loader. Be sure
    # that you add style-loader to your project dependencies.
    #
    # If you want to instead deliver CSS via <link> with the mini-extract-css-plugin, set inline_css to false.
    # In that case, style-loader is not needed as a dependency.
    #
    # mini-extract-css-plugin is a required dependency in both cases.
    inline_css: true
    # Defaults to the inverse of hmr. Uncomment to manually set this.
    # live_reload: true
    client:
      # Should we show a full-screen overlay in the browser when there are compiler errors or warnings?
      overlay: true
      # May also be a string
      # webSocketURL:
      #  hostname: "0.0.0.0"
      #  pathname: "/ws"
      #  port: 8080
    # Should we use gzip compression?
    compress: true
    inline: true
    overlay: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    # Note that apps that do not check the host are vulnerable to DNS rebinding attacks
    allowed_hosts: "all"
    pretty: true
    headers:
      'Access-Control-Allow-Origin': '*'
    static:
      watch:
        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

  # Cache manifest.json for performance
  cache_manifest: true

Static website on which I want to embed my component

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Web Page</title>
</head>

<body>
    <header>
        <h1>Welcome to My Web Page</h1>
    </header>

    <nav>
        <!-- Add navigation links here -->
        <!-- Example:
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Contact</a></li>
        </ul>
        -->
    </nav>

    <main>
        <section>
            <h2>Section 1</h2>
            <!-- Add content for section 1 here -->
        </section>

        <section>
            <h2><div id="my-react-component"></div></h2>
            <!-- Add content for section 2 here -->
        </section>

        <!-- Add more sections as needed -->
    </main>

    <footer>
        <p>&copy; 2023 Your Website</p>
    </footer>
    <script src="http://localhost:3066/embed.js"></script>

</body>

</html>
dbugger
  • 15,868
  • 9
  • 31
  • 33
Panczo
  • 424
  • 5
  • 20

0 Answers0