React on rails not rendering - ruby-on-rails

I am trying to render my react component on my ruby on rails app. There is no error but the page renders nothing. I suspect if the tutorial is outdated or if failed to asked me to import some stuff.
I followed closely to this site: https://medium.com/quick-code/simple-rails-crud-app-with-react-frontend-using-react-rails-gem-b708b89a9419
This is probably the most critical part of the tutorial.
Let’s return to config/routes.rb for a second and add our Home index page to be the root:
root to: 'home#index'
Now all our index page need is a corresponding view. Create a new ‘home’ folder inside app/views and add index.html.erb file to it:
app/views/home/index.html.erb
This file will only contain one line that takes advantage of react_component view helper that comes with ‘react-rails’ gem. It’s not going to work right now, but it all will make sense in a moment.
<%= react_component 'Main' %>
Creating our first React Component
Create a file named app/assets/javascripts/components/_main.js.jsx
We are going to follow the usual syntax for creating a stateless/presentational React Component that we will call Main:
const Main = (props) => {
return(
<div>
<h1>Fruits are great!</h1>
</div>
)
}
Head to localhost:3000 in the browser and see for yourself that our first Component was loaded on the page. Pretty cool!
I tried to include code like
import React from "react"
import ReactDOM from 'react-dom';
but nothing renders too.
When trying to debug, I tried not to deviate from the tutorial as I am still new and hope to learn from one source at a time to prevent conflicting and different methods.

Related

How to use stimulus components with rails import maps

I want to include this stimulus component into my brand new rails 7 app:
https://www.stimulus-components.com/docs/stimulus-dropdown
When I follow their setup approach, i get the following error in my browser console:
platforms#:1 Uncaught TypeError: Failed to resolve module specifier "stimulus-dropdown". Relative references must start with either "/", "./", or "../".
I found this article on stackoverflow:
Failed to resolve module specifier "stimulus-autocomplete"
which suggests to add a "pin" to my importmap.rb.
So i took the dropdown link from here https://www.jsdelivr.com/package/npm/stimulus-dropdown
and put it into my importmap.rb by:
pin "stimulus-dropdown", to: "https://cdn.jsdelivr.net/npm/stimulus-dropdown#2.0.0/dist/stimulus-dropdown.min.js"
But it doesnt work and displays a 404 in my browser console.
I hope someone can help, there must be an easy way to use stimulus-components in a brand new rails 7 app.
i was also struggling but i have figured it out
first run -
./bin/importmap pin stimulus-dropdown
second create a stimulus controller called 'dropdown' -
rails g stimulus dropdown
then copy-paste the following code into the dropdown controller
import { Application } from '#hotwired/stimulus'
import Dropdown from 'stimulus-dropdown'
const application = Application.start()
application.register('dropdown', Dropdown)
After you do all the above you are ready to use stimulus drop-down in your
views. for the view example check the docs on the site.
I suggest adding it with yarn as well with yarn add stimulus-dropdown. This worked for me when I faced your issue.

Using Rails data as the defaultProps in react component

I'm using react-rails (with sprockets rather than webpack, if it turns out to be relevant), trying to make a reusable component for a sprawling rails application. It's basically a navbar, and we have a list of links we usually want to display, but we also need to be able to override that list on some pages.
So far so good. However!
We have the array of links saved as a constant in our rails app, and ideally, the default links would be the defaultProps for the react component. We don't want to duplicate that information in the react component, because the whole point of making this component is that we're trying to move toward consistency, and if we need to make updates hopefully we'll only make them in one place.
So this is an option:
<%= react_component "Navbar", links: navbar_default_links, other_settings: true, etc: false %>
But having to do that on every page seems inelegant when really we just want to call out when the links are different than the usual ones.
Does anyone know a way to pull information from Rails into the definition of the react component using react-rails? Or another solution?
(Edit: to be clear, this doesn't need to be information from the rails database)
Here are the ways I'm aware of to communicate to share constants between Rails and React.
Option #1: Wrap react_component
def render_navbar(props = {}, options = {})
react_component 'Navbar', {links: navbar_default_links}.merge(props), options
end
Option #2: (If you use Webpack) Declare the links in a JSON or YAML that both Rails and your bundler can consume.
# The file that used to define the constant
def navbar_default_links
JSON.load(File.read(Rails.root.join('path/to/your/file.json')))
end
// In `Navbar.js`, using json-loader
import navbarDefaultLinks from './path/to/navbar_default_links.json';
Option #3 (If you use the Asset pipeline) Add .erb to your JS file and use the constant
// Navbar.js.erb
const defaultProps = <%= MyModule::NAVBAR_DEFAULT_LINKS %>
Options #4 Communicate through a global object like window. It breaks encapsulation but hey 🤷‍♂️
In application.html.erb
<script>
window.navbar_default_links = <%= MyModule::NAVBAR_DEFAULT_LINKS %>
</script>
<%= `window.navbar_default_links` must be above this line %>
<%= javascript_pack_tag 'application' %>
// In `navbar.js`
const navbarDefaultLinks = window.navbar_default_links

How use react components from npm in rails

I am new in react and I follow this article https://www.airpair.com/reactjs/posts/reactjs-a-guide-for-rails-developers
to use react in rails app and everything was fine. But later I wanted include in records.html page summernote (WYSIWYG html editor). I found this npm module react-summernote and can't make editor works.
This is my code (try 1):
application.js
var ReactSummernote= window.ReactSummernote = global.ReactSummernote = require('react-summernote');
index.html.erb
<%= react_component 'ReactSummernote'%>
This is my code (try 2):
summernote.js.coffee
#RichTextEditor = React.createClass
render: ->
React.createElement ReactSummernote
index.html.erb
<%= react_component 'RichTextEditor'%>
and got this error
react.self-e3251ec….js?body=1:1285 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of Constructor.
Some things worth checking;
I'm assuming your node packages are being installed to /node_modules/*. Make sure those packages are being added to your asset pipeline. I've used browserify to accomplish this.
Check in your browser console to see if the variable is being set (just type ReactSummernote. The result should be a function if it is imported correctly, or undefined if there is some problem).
If you've gotten this far and are still stuck, I would recommend triggering the render without using react-rails. It's easy enough to render the component onload of your page through vanilla javascript, and if it's the react-rails gem that is causing you problems, this will navigate around it easily with something like this;
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);

Using a single html template for Rail view and Angular Template

I have a Ruby on Rails app that loads a single page Angular JS Web App when the user is logged in, and serves static info pages via RoR views when the user is not logged in.
The angular templates are in 'app/assets/templates/' and the rails files are in 'app/views'.
I have a text heavy html page that I would like re-use with both rails and angular. I've tried accessing the rails view from my angular $routeProvider, setting templateURL to the path of the view. This causes more than one instance of angular to load and it gets stuck in a loop.
app.config ($routeProvider) ->
$routeProvider.when('/features/',
templateUrl: '/views/features.html'
)
I've tried rendering the file in my assets/templates folder through a rails view. That doesn't work either since rails can't find the partial.
= render 'assets/templates/features.html'
Does anyone know how I might be able to use a single template for both?
I'm mot sure what exactly you mean by text heavy page. But what about other solution - extract all text to JSON file with keys (some sort of translation file). For example:
{ "title1": "Title", "paragraph1": "lore up sum. .." }
Then you can load this JSON in your rails controller and pass it to view that render text parts from it.
<h1><%= #text ['title1'] %></h1>
<p><%= #text['paragraph1'] %></p>
And as well load JSON as resource in your angular app and pass it to view.
<h1>{{ text.title1 }}</h1>
<p>{{ text.paragraph1 }}</p>
If your text is somehow structured you can make use if it and automate the view with loops, conditions etc and so save repeated parts even more.

Getting an empty space when trying to use gmaps4rails

So I followed the tutorial and screencast but can't seem to get this to work. I can see the div id's called map container and gmaps4rails_map where presumably, the map is supposed to be but nothing else.
I put in the yield :head and yield :script in the header and footer of the application layout view and #charger = Charger.all.to_gmaps4rails (Charger is my model) in the chargers_helper.html.erb file (I want to use in User show view).
I also put <%= gmaps4rails(#charger) %> in the show.html.erb view.
How do I get this to work?
-Update-
I just got it to work. To fix the problem I put in the #charger = ... code in a method in the helper and called the method instead of #charger.
Now the map shows up but I still cannot see the insert new marker code like in the screencast - I don't need it for my app but am curious as to what happened to it.
In the screencast, I create model + controller with a scaffold generator. That's why I have ready to use links.
Besides, I create buttons during the screencast. Nothing is made behind the scene: the whole app is created from scratch :)

Resources