Rails + React App Pages Require Reload To Render React - ruby-on-rails

I created a new Rails + React app using rails new exampleapp --webpack=react. On my home page, I have a header in html.erb, and some react jsx being rendered using <%= javascript_pack_tag 'reactfilename' %>.
When I click on a link to my home page, such as <li><%= link_to "Home", root_path %></li>, only the header is rendered. It is only till I reload the page that my react component is shown.
I am running both rails s and ./bin/webpack-dev-server to start my application. The same problem is occurring on my Heroku web server. in which I have the following setup:
Procfile:
web: bin/rails server -p $PORT -b 0.0.0.0
Procfile.dev:
web: ./bin/rails server
webpacker: ./bin/webpack-dev-server
Is this the expected behaviour of a React + Rails app, or is there a problem in my configuration?

I believe this issue has something to do with turbolinks background optimization. One workaround is to cause a complete refresh of the page by setting turbolinks to false:
<%= link_to "Home", root_path, data: { turbolinks: false } %>
With newer versions of turbolinks:
<%= link_to "Home", root_path, data: { turbo: false } %>

make sure you are loading you component after turbolink:load event
document.addEventListener('turbolinks:load', () => {
let container = document.getElementById('react-order')
if (!container) return
ReactDOM.render(
<OrderForm />,
container)
})

Related

I'm stuck trying to add Quilljs to a Rails 5.1 app via Webpack

I have been trying to add Quill editor to my app but it doesn't work.
I created a Rails 5.1 app with --webpack and then I ran rails webpacker:install
I ran yarn add quill and rails webpacker:compile
I added <%= javascript_pack_tag 'application' %> to layouts/application.html.erb
In packs/application.js I have:
import Quill from 'quill';
var quill = new Quill('#article_content', {
theme: 'snow'
});
In _form.html.erb:
<%= form.text_field :content, id: :article_content %>
I ran rails s and .bin/webpack-dev-server
In console i get an error: quill Invalid Quill container #article_content
What did I do wrong?
I'm assuming that you are using Turbolinks too. You need to make sure that you are wrapping the following script with:
document.addEventListener("turbolinks:load", function() {
var quill = new Quill('#article_content', {
theme: 'snow'
});
})
This solved the problem for me
It's not clear when _form.html.erb is being included but that error means when new Quill was run, there was no DOM element on the page that matched the input query. Specifically for your case, that means there was no element on the page that has an ID article_content.
var quill = new Quill('#article_content', {
theme: 'snow'
});
You can not use a css id selector here, just class works. So change id="article_content" to class="article_content" ad then your snippet to:
var quill = new Quill('.article_content', {
theme: 'snow'
});
and you are ready to go.

Angular ui-router templates are not loading, Rails backend

I'm following along with the Angular/Rails tutorial at Thinkster and I've run into an issue which seems to be most likely be Angular-related. Everything works just fine until I get to the Angular Routing section. Simply put, the inline templates within the <script> tags do not load in the <ui-view></ui-view> element. I originally thought this may be due to having opened the page locally as a file rather than having it loaded from a server, but the same problem persists even after integrating Rails (using an older version of Sprockets, as pointed out in this similar but unrelated issue).
When I load the index page in either the browser as a file or as a URL when running the Rails server, I've inspected the HTML and, sure enough, the only thing it shows in the code are the divs and an empty <ui-view> element, indicating something just isn't adding up correctly. I've tried various things, including:
Using the newest version of ui-router (0.2.15 at this writing) rather than the version in the tutorial
Using <div ui-view></div> instead of <ui-view></ui-view>
Changing the value of 'url' in the home state to 'index.html', including using the full path to the file (file:///...)
Putting the contents of the inline <script> templates into their own files (without the <script> tags, of course) and specifying the 'templateUrl' field using both relative and full paths
Trying both Chrome and Firefox just to be extra certain
None of these things have worked, even when accessing http://localhost:3000/#/home when the Rails server is running after having integrated Angular into the asset pipeline in the Integrating the Front-end with the Asset Pipeline section of the tutorial. Indeed, the route loads but does not show anything more than a completely blank page with a lonesome and empty <ui-view> element when inspecting the HTML using Chrome's dev tools.
Given that the issue seems to occur even before the Rails portion, it does seem like something to do with Angular itself, but I've got no clue what's going on, especially since I've followed along to the letter.
I'm using Bower to manage the Angular dependencies and the HTML does show that the Angular javascript files in both the app/assets/javascripts directory and in the vendor/assets/bower_components directory are being loaded properly in the <head> section, so everything seems to be okay on the asset pipeline integration.
Versios I'm using:
Rails: 4.2.3
Ruby: 2.2.1p85
Angular: 1.4.3
ui-router: 0.2.15
The code I've got for the major moving parts is below:
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Test App</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
</head>
<body ng-app="testApp">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</div>
</body>
</html>
app/assets/javascripts/app.js
angular.module('testApp', ['ui.router', 'templates']).config(['$stateProvider', '$urlRouteProvider', function($stateProvider, $urlRouteProvider) {
$stateProvider
.state('home', {
'url': '/home',
'templateUrl': 'home/_home.html',
'controller': 'MainCtrl'
})
.state('posts', {
'url': '/posts/{id}',
'templateUrl': 'posts/_posts.html',
'controller': 'PostsCtrl'
});
$urlRouteProvider.otherwise('home');
}]);
app/assets/javascripts/application.js
//= require angular
//= require angular-rails-templates
//= require angular-ui-router
//= require_tree .
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
respond_to :json
def angular
render 'layouts/application'
end
end
config/routes.rb
Rails.application.routes.draw do
root to: 'application#angular'
end
app/assets/javascripts/home/mainCtrl.js
angular.module('testApp').controller('MainCtrl', ['$scope', 'posts', function($scope, posts) {
$scope.posts = posts.posts;
$scope.addPost = function() {
if (!$scope.title || $scope.title === "")
return;
$scope.posts.push({
'title': $scope.title,
'link': $scope.link,
'upvotes': 0,
'comments': [
{'author': 'Some Person', 'body': 'This is a comment.', 'upvotes': 0},
{'author': 'Another Person', 'body': 'This is also a comment.', 'upvotes': 0}
]
});
$scope.title = "";
$scope.link = "";
};
$scope.incrementUpvotes = function(post) {
post.upvotes++;
};
}]);
app/assets/javascripts/posts/postsCtrl.js
angular.module('testApp').controller('PostsCtrl', ['$scope', '$stateParams', 'posts', function($scope, $stateParams, posts) {
$scope.post = posts.posts[$stateParams.id];
$scope.addComment = function() {
if($scope.body === '')
return;
$scope.post.comments.push({
'body': $scope.body,
'author': 'user',
'upvotes': 0
});
$scope.body = '';
};
}]);
app/assets/javascripts/posts/posts.js
angular.module('testApp').factory('posts', ['$http', function($http) {
var o = {
'posts': []
};
o.getAll = function() {
return $http.get('/posts.json').success(function(data) {
angular.copy(data, o.posts);
});
};
return o;
}]);
If any other code is required to help uncover the problem, please let me know and I'll supply anything requested.
it seems that the angular-ui-router is incompatible with the new Rails sprockets. To fix this, add this earlier version of sprockets to your gemfile:
gem 'sprockets', '2.12.3'
And then run bundle update sprockets.
This was answered a few times in other similar questions, like the one below:
Angular Rails Templates just not working
$urlRouteProvider in my code should've been $urlRouterProvider. Be sure to double-check everything, folks, and make good use of the console!

Rails 2.3.14 No Route for .js.erb File

In my layout footer I am including page specific JavaScript files like so:
<%= javascript_include_tag "#{params[:controller]}_#{params[:action]}" if javascript_exists?("#{params[:controller]}_#{params[:action]}") %>
The helper I am using is from another question on this site but modified to work with Rails 2:
application_helper.rb
def javascript_exists?(script)
script = "#{RAILS_ROOT}/public/javascripts/#{script}.js"
extensions = %w(.coffee .erb .coffee.erb) + [""]
extensions.inject(false) do |truth, extension|
truth || File.exists?("#{script}#{extension}")
end
end
Then I also init the included file:
<script>
jQuery(document).ready(function() {
<%= "#{params[:controller].titleize}#{params[:action].titleize}.init();" if javascript_exists?("#{params[:controller]}_#{params[:action]}") %>
});
</script>
This works perfectly fine if my file is named controller_action.js but once renamed to controller_action.js.erb Rails generates an error because it can't find it.
GET http://localhost:3000/javascripts/controller_action.js 404 (Not Found)
Uncaught ReferenceError: ControllerAction is not defined
Update
If I use the .rjs extension then there are no errors generated but this seems to be because Rails doesn't think the file exists. (I updated the javascript_exists? with the .rjs extension.)
After some more debugging, the file is being located:
/path/public/javascripts/circuit_list.js true
but this returns false if .rjs is used.
The routing error when navigating to http://localhost:3000/javascripts/controller_action.js in the browser is:
No route matches "/javascripts/controller_action.js" with {:method=>:get}

Content for doesn't work in production mode

On one of application's page there is:
<% content_for :head do %>
<%= tag :meta, property: "fb:app_id", content: ENV["FACEBOOK_APP_ID"] %>
<% content_for :title, #check.title %>
<% end %>
And it worked in development, while I was running server at my localhost.
After that I deployed application on heroku. And that simply doesn't work.
What means doesn't work. I load page in development at localhost:
<title>Tenta</title>
<meta content="*****************" property="fb:app_id">
When I load this page deployed at heroku host, these tags are simply absent.
Why?
Also, If you don't know this particular issue solution, I would appreciate if you adivce me, how can I look what is going on - heroku logs and watching last 150 logs in inconvinient windows console doesn't give me a lot of helpful information.

Why Ajax renders 2 views in rails 3.1 app

When entering log in our rails 3.1 app, ajax is used to render the input screen below. Here is the link for log:
<%= link_to 'Log', new_part_out_log_path(#part, :format => :js), :remote => true, :id => 'new_log_link' %>
And the new.js.erb as this:
$("<%= escape_javascript render(:file => 'out_logs/new.html.erb') %>").insertAfter('#new_log_link');
$('#new_log_link').hide();
$('#close').hide();
the problem is that after clicking 'Log', instead of one view, 2 identical views of out_logs/new.html.erb were rendered. What may be wrong with our code? thank so much.
The problem is related to upgrade to ruby 1.9.3 which causes webrick server (for development) warning message and also rendering the .js.erb file twice on screen. The twice rendering problem disappears on our production server which is running nginx. The following link may help to understand the problem:
http://theresa.multimediatechnology.at/webrick-warnings-in-ruby-1-9-3/
What does "WARN Could not determine content-length of response body." mean and how to I get rid of it?

Resources