Una guía completa para configurar una aplicación de Javascript de una sola página con React y Redux dentro de un proyecto de Rails.

Actualización (17 de marzo de 2019): Se agregó mecanografiado al último paso de este proyecto.
Este tutorial le mostrará cómo crear una aplicación de una sola página con React (y Redux y Semantic UI) dentro de un proyecto Rails.
Este tutorial también incluirá:
- Redux
- Reaccionar enrutador
- Volver a seleccionar
- Redux Think
- Interfaz de usuario semántica
Nota al margen # 1. Recientemente vi esta maravillosa guía y me inspiró a escribir una para Rails.
Nota al margen # 2. Aquí está el tutorial terminado. El historial de confirmaciones se corresponde (en cierto modo) con los pasos de esta guía.
Visión general
Para darle una idea de lo que vamos a construir y cómo funcionarán las cosas, vea los 2 diagramas a continuación.
Diagrama 1: Manejo de la primera solicitud HTTP (es decir, solicitudes del navegador a nuestra aplicación Rails)
El diagrama a continuación ilustra su aplicación React dentro de su proyecto Rails y la ruta (línea negra continua) que toma la primera solicitud para devolver la aplicación React al cliente (navegador).

Diagrama 2: Manejo de solicitudes HTTP posteriores (es decir, solicitudes de nuestra aplicación React a nuestra aplicación Rails)
Después de que la aplicación React se cargue en el navegador del usuario, la aplicación React será responsable de enviar solicitudes a su aplicación Rails (línea negra continua). En otras palabras, una vez que se carga React, las solicitudes a Rails provendrán del código Javascript y no del navegador.

Otras notas importantes antes de empezar a codificar
- Piense en su aplicación React como algo independiente de su aplicación Rails. La aplicación React es estrictamente para el front-end y se ejecuta en el navegador del usuario. La parte de Rails es estrictamente para el back-end y se ejecuta en el servidor. La aplicación Rails no sabe nada sobre la aplicación React, excepto cuándo devolver sus activos estáticos (HTML, JS y CSS compilados por Webpack).
- Una vez que su navegador carga la aplicación React, toda la lógica para realizar solicitudes HTTP (recuperar datos y convertir esos datos en una vista) se realiza en el front-end (es decir, el navegador).
- Su aplicación Rails efectivamente no ofrece ninguna vista excepto la que sirve a su aplicación React. En este tutorial, la única vista de Rails es
/app/views/static/index.html.erb
- Todas las
/api/*
rutas son manejadas por la aplicación Rails, mientras que todas las demás rutas son manejadas por React dentro del navegador (después de que su navegador haya cargado la primera solicitud). Por ejemplo,//your-app.com/something
se enviará a la aplicación Rails y luego se devolverá a su aplicación React (el HTML / JS / CSS que ya se cargó en el navegador), que decidirá qué mostrar en la pantalla. - Consideraciones para crear una aplicación de una sola página. No es necesario para este tutorial, pero es útil.
- Reaccionar patrones de diseño de componentes. De nuevo, no es necesario pero sí útil.
Requisitos del sistema
FYI aquí está la configuración de mi sistema. No digo que lo necesite, pero algo similar hará que la experiencia de este tutorial sea más fluida.
- macOS 10.13.6 (High Sierra)
- Ruby 2.5.1
- Rails 5.2.1 (y Bundler 1.16.6)
- - paquete de instalación de gemas -v 1.16.6
- Nodo 9.8.0
Finalmente, ¡vamos al código!
Paso 1: crea un nuevo proyecto de Rails con Webpack y React
Crea una nueva aplicación Rails. He nombrado el mío rails-react-tutorial
.
rails new rails-react-tutorial --webpack=react
Consulte aquí para obtener más información sobre la --webpack=react
bandera introducida en Rails 5.1.
Paso 2: asegúrese de que las gemas Webpacker y React-Rails estén instaladas
Compruebe si las gemas Webpacker y React-Rails están en su Gemfile
. Si las gemas no están allí, agréguelas:

Ahora ejecute estos comandos para instalar todo.
bundle install
# This command might not be necessary.# If already installed, then it will# ask you to override some files.rails webpacker:install
rails webpacker:install:react rails generate react:installyarn install
Ahora ejecute rails server -p 3000
y visite //localhost:3000
para asegurarse de que nuestro proyecto esté funcionando.
Consejo profesional n. ° 1 : ejecute ./bin/webpack-dev-server
en una ventana separada mientras codifica para que los cambios generen y recarguen automáticamente el navegador.
Consejo profesional n. ° 2 : si obtiene este error can’t activate sqlite3 (~> 1.3.6), already activated sqlite3–1.
4.0, entonces un dd gem ‘sqlite3’, ‘~>
1.3.6 'a Gemfile. Consulte este enlace para obtener más información.
Paso 3: agregue una clase de controlador y una ruta a nuestra aplicación Rails
Agrega una nueva ruta a nuestra aplicación Rails. Para este ejemplo, agregaremos un GET /v1/things
punto final a config/routes.rb
`.

Esta nueva ruta requerirá un ThingsController. Crea un nuevo app/controllers/v1/things_controller.rb
archivo. Recuerde, debe estar en la v1
carpeta porque pertenece a nuestra API Rails.

Nuestro controlador Things devolverá una respuesta codificada de forma rígida para GET /v1/things
.
En este punto, debería poder volver a ejecutar rails server -p 3000
y visitar //localhost:3000/v1/things
.

A continuación, crearemos un nuevo componente React.
Paso 4: Genere un nuevo componente React
Cree un componente HelloWorld React que acepte un parámetro String llamado greeting
ejecutando el siguiente comando:
rails generate react:component HelloWorld greeting:string
Un archivo debe ser creado: app/javascript/components/HelloWorld.js
.

Paso 5: use nuestro componente HelloWorld
Para usar y ver nuestro nuevo componente HelloWorld, necesitamos 2 cosas: crear una vista que incorpore este componente y agregar una ruta para apuntar a esta vista.
Para crear una vista, cree el archivo app/views/static/index.html.erb
y agregue lo siguiente:

Para nuestra nueva ruta, agregue la siguiente línea a nuestro routes.rb
archivo y un StaticController vacío para admitirlo.

Agregue esto a app/controllers/static_controller.rb
:

Ahora debería poder volver a ejecutar rails server -p 3000
y visitar //localhost:3000/
para ver su nuevo componente de React (recuerde ejecutar ./bin/webpack-dev-server
en una ventana separada para que los cambios de Javascript sean empaquetados automáticamente por webpack).

Ahora que tenemos un componente React que se renderiza en nuestra vista, expandamos nuestra aplicación para admitir múltiples vistas con react-router
.
Paso 6: Agregar React-Router
Primero, ejecute este comando para agregar react-router-dom
, que incluye y exporta todos react-router
y algunos componentes auxiliares adicionales para la navegación web. Más info aquí.
npm install --save react-router-domyarn install
Este comando debe agregar la siguiente línea a su package.json
archivo. Tenga en cuenta que aquí se utilizó 4.2.2, pero su versión podría ser diferente.

Ahora usemos React Router para hacer algunas rutas para nuestro React Front-End.
Paso 6: uso de React-Router
react-router
nos permite gestionar todas nuestras rutas de UI estrictamente con Javascript. Esto significa que necesitaremos un único componente de "Aplicación" que encapsule toda nuestra aplicación. La "Aplicación" también utilizará React-Router para presentar el componente "Página" correcto para la URL que se solicita.
Para comenzar, ejecute este comando para agregar un componente de la aplicación que representará toda nuestra aplicación de front-end.
rails generate react:component App
A continuación, abra el archivo para el componente React recién creado app/javascript/components/App.js
, y agregue lo siguiente ...

Ahora cambie index.html.erb
para señalar nuestro nuevo componente de aplicación.

Por último, edite su routes.rb
para que Rails envíe todas las solicitudes que no sean para la API a nuestro componente de aplicación (vía StaticController#index
).

Ahora podemos ejecutar rails server -p 3000
y visitar //localhost/
y //localhost/hello
ver el funcionamiento de React-Router (recuerde que ./bin/webpack-dev-server
habilita el paquete web automático).
A continuación, necesitaremos instalar algunas dependencias adicionales antes de que podamos conectar nuestro front-end React a nuestra API Rails.
Paso 7: Agregar Redux, Sagas, Babel Polyfill y Axios
Ahora agreguemos las siguientes bibliotecas de Javascript para nuestro front-end.
- Redux para gestionar el estado global de nuestra aplicación.
- Babel-Polyfill para habilitar funciones de Javascript sofisticadas que de otra manera no estarían disponibles en navegadores web más antiguos
- Vuelva a seleccionar y React-Redux para facilitar el trabajo con Redux.
Para instalar todo, ejecute lo siguiente:
npm install --save redux babel-polyfill reselect react-reduxyarn install
Ahora usaremos estas herramientas para configurar un Redux State Store, luego agregaremos algunas Acciones y Reductores para usarlo.
Paso 8: configurar Redux State Store
En este paso, configuraremos Redux State Store para nuestra aplicación con la siguiente plantilla (agregaremos y eliminaremos "cosas" en los siguientes pasos).
{ "things": [ { "name": "...", "guid": "..." } ]}
Primero, cree un configureStore.js
archivo. Esto inicializará nuestra tienda Redux.

Ahora importe y utilícelo configureStore()
en el componente de la aplicación para crear un estado de Redux y conéctelo a nuestra aplicación.

¡Ahora tienes Redux instalado en tu aplicación! A continuación, crearemos una Acción y un Reductor, y comenzaremos a escribir y leer desde nuestro Estado Redux.
Paso 9: agregue una acción y un reductor
Ahora que la aplicación tiene un estado Redux, agregaremos un
y the rootRed
ucer().
First, add
getThings()
Action definition and import createStructuredSelector()
and connect()
into theHelloWorld Component. This maps parts of the Redux State, and Actions (i.e. dispatching getThings()
) , to HelloWorld’s prop.
Next, add a
hes a getTh
ings() Action (from ./actions/index.js) on every click.

After everything is added to HelloWorld, go to //localhost:3000/hello
, open the Console, and click the “getThings” button to see your Action and Reducer functions being called.

Now that you can send an Action that can be received by a Reducer, let’s have the Reducer alter the Redux State.
Step 10: Have HelloWorld read React State and display “things”
Insert a List <
ul> in HelloWorld and fill it with “things” from your Redux State.

To test if this is actually working, we can initialize with some “things” data. Once this is done, we can refresh the page and see it in our list.

Now that we have a simple Action and Reducer working, we will extend this so that the Action queries our Rails API and the Reducer sets the content of “things” with the API response.
Step 11: Install Redux-Thunk
We will need Redux-Thunk to allow async workflows (like an HTTP request) to dispatch Actions.
Install redux-thunk
by running this command:
npm install --save redux-thunkyarn install
Now, let’s use Thunk in our Action!
Step 12: Use redux-thunk and fetch() to query API and set React State with results
First, let’s import redux-thunk
in configureStore.js
and install it our Redux Store so our App can handle “Thunk” Actions.

Now test that everything is working by starting the App and loading a page.
Next, let’s change the getThings()
Action to return a function that performs the following (instead of returning the Action object):
- Dispatch the original Action object
- Make a call to our Rails API.
- Dispatch a new Action
getThingsSuccess(json)
when the call succeeds.
For this step, we will also need to add the getThingsSuccess(json)
Action.

Of course, this does nothing to the Redux State since our Reducer is not making any changes. To fix this, change the Reducer to handle the GET_THINGS_SUCCESS
Action and return the new State (with the response from the Rails API).

Now if you start your App, navigate to localhost:3000/hello
and click the button, your list should change!

There you have it. A Rails API hooked up to a React+Redux App.
(Bonus) Step 13: Installing Redux Dev Tools
Maybe I should’ve put this step earlier, but Redux Dev Tools is essential for debugging the Actions your App is sending, and how those Actions are changing your State.
This is how you install it. First, install the proper extension for your browser (Chrome, Firefox).
Next, run the following to install the library.
npm install --save-dev redux-devtools-extensionyarn install
Now, use it to initialize your Redux State Store.

After all this is done, you should be able to see a new tab, Redux, in your Chrome (or Firefox) dev tools, that lets you see which Actions were dispatched, and how each one changed the App’s State. The React tab will also show you all your components and their props and states.

Happy debugging!
(Bonus) Step 14: Semantic UI
Semantic is a great library for UI components that makes it really easy to build nice looking websites quickly.
To install this library, run the following.
npm install --save semantic-ui-css semantic-ui-reactyarn install
Add this to app/javascript/packs/application.js
:
import 'semantic-ui-css/semantic.min.css';
And add this to app/views/static/index.html.erb
:
'all' %


(Bonus) Step 15: Using a Reasonable Directory Structure
This step is totally optional, and it has nothing to do with the function of the App. Just my opinion on how you should organize your files.
So as you can probably guess, stuffing your Actions into the same file as your Components, and having a single reducer for your entire App, does not scale very nicely when your App grows. Here is my suggested file structure:
app|-- javascript |-- actions |-- index.js |-- things.js |-- components |-- packs |-- reducers |-- index.js |-- things.js
(Bonus — Mar 17 2019 Update) Step 16: Install Typescript!
Typescript is just like Javascript but with types! It is described as a “strict syntactical superset of Javascript”, meaning that Javascript is considered valid Typescript, and the “type features” are all optional.
IMO Typescript is fantastic for large Javscript projects, such as a big React front-end. Below are instructions on how to install it, and a small demo of it inside our project.
First, run the following commands (taken from the Webpacker Readme):
bundle exec rails webpacker:install:typescriptyarn add @types/react @types/react-dom
Now, to see it in action, let’s rename app/javascript/reducers/things.js
to things.tsx
and add the following lines to the top of the file:

After you add interface Thing
, let’s use it by having const initialState
use that type (seen in the screenshot above), and specify that thingsReducer
return an array of type Thing
(also seen in the screenshot).
Everything should still work, but to see Typescript in action, lets add a default
case to thingsReducer
and add return 1
. Since 1
is not a Thing
type we will see the output of ./bin/webpack-dev-server
fail with the following:

And that’s it! You can now add Typescript .tsx
files to your project and start using Types with your project.
Here’s a great overview of Typescript and why you should use it.
The End
You made it! You’ve made a Rails App that uses React and Redux. That’s pretty much it for the tutorial. I hope you had fun and learned something along the way.
If you build something with React and Rails, please do share it in the comments below — along with any questions or comments you may have for me.
Thanks for reading!