I'm working with a Rails 6 rc1 project with React and Webpacker.
I'm currently using javascript_pack_tag
to render React components in my Rails app. I'm trying not to use a gem like react-rails
just to keep things simple.
Today I found a weird behavior where my React component would not render after the page is navigated to from a link. However, on a page reload, my component is rendered.
Gemfile
:
gem 'rails', '~> 6.0.0.rc1'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
gem 'sass-rails', '~> 5'
gem 'webpacker', '~> 4.0'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
gem 'bootsnap', '>= 1.4.2', require: false
gem 'devise', '~>4.6'
group :development, :test do
gem 'pry-byebug'
gem 'rspec-rails', '~> 3.8'
end
group :development do
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
app/views/layouts/application.html.erb
:
<html>
<head>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
....
app/javascript/packs/application.js
:
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
import "bootstrap"
import "../stylesheets/application"
app/views/posts/new.html.erb
:
<%= content_tag :div,
id: 'post_data',
data: @post do %>
<% end %>
<div id="render_here"></div>
<%= javascript_pack_tag 'new_post' %>
app/javascript/packs/new_post.jsx
: (though the React code in this file isn't really relevant for the question)
import React from 'react';
import ReactDOM from 'react-dom';
import PostForm from '../components/PostForm';
document.addEventListener('DOMContentLoaded', () => {
const node = document.getElementById('post_data');
const data = JSON.parse(node.getAttribute('data'));
const dom = document.querySelector('#render_here');
ReactDOM.render(
<PostForm post={data} />,
dom);
});
With this setup, the component is not rendered after clicking on a link that navigates to the page. On page reload, the component is rendered.
I tried a number of things.
In new_post.jsx
, after commenting everything out and leaving only console.log(document.readyState)
, the console displays complete
twice. On page load, it displays loading
.
Then I tried to use jQuery's document.ready
in new_post.jsx
:
$(document).ready(function() {
if (pageInitialized) {
return;
}
pageInitialized = true;
console.log('render');
...
And again, render
is displayed twice after the page is navigated to. On page reload, render
is displayed once.
What is going on?