Comment créer un projet Rails avec un front-end React et Redux

Un guide complet pour configurer une application Javascript d'une seule page avec React et Redux dans un projet Rails.

Mise à jour (17 mars 2019): Ajout de Typescript à la dernière étape de ce projet.

Ce didacticiel vous montrera comment créer une application d'une seule page avec React (et Redux et l'interface utilisateur sémantique) dans un projet Rails.

Ce tutoriel comprendra également:

  • Redux
  • Routeur React
  • Sélectionner de nouveau
  • Redux Think
  • UI sémantique

Note d'accompagnement n ° 1. J'ai vu ce merveilleux guide récemment et cela m'a inspiré d'en écrire un pour Rails.

Note d'accompagnement n ° 2. Voici le tutoriel terminé. L'historique des validations correspond (en quelque sorte) aux étapes de ce guide.

Aperçu

Pour vous donner une idée de ce que nous allons construire et de la façon dont les choses vont fonctionner, voyez les 2 schémas ci-dessous.

Diagramme 1: Traitement de la première requête HTTP (c'est-à-dire les requêtes du navigateur à notre application Rails)

Le diagramme ci-dessous illustre votre application React dans votre projet Rails et le chemin (ligne noire continue) que prend la première requête pour renvoyer l' application React au client (navigateur).

Diagramme 2: Gérer les requêtes HTTP suivantes (c'est-à-dire les requêtes de notre application React vers notre application Rails)

Une fois l'application React chargée dans le navigateur de l'utilisateur, l'application React sera responsable de l'envoi des demandes à votre application Rails (ligne noire continue). En d'autres termes, une fois React chargé, les requêtes adressées à Rails proviendront du code Javascript et non du navigateur.

Autres notes importantes avant de commencer à coder

  • Considérez votre application React comme étant distincte de votre application Rails. L'application React est strictement destinée au front-end et s'exécute dans le navigateur de l'utilisateur. La partie Rails est strictement réservée au back-end et s'exécute sur le serveur. L'application Rails ne sait rien de l'application React, sauf quand renvoyer ses actifs statiques (Webpack compilé HTML, JS et CSS).
  • Une fois que votre application React est chargée par votre navigateur, toute la logique pour effectuer des requêtes HTTP (récupérer des données et transformer ces données en vue) se fait dans le front-end (c'est-à-dire le navigateur).
  • Votre application Rails ne diffuse aucune vue à l'exception de celle qui sert votre application React. Dans ce didacticiel, la seule vue Rails est/app/views/static/index.html.erb
  • Tous les /api/*chemins sont gérés par l'application Rails, tandis que tous les autres chemins sont gérés par React dans le navigateur (une fois que votre navigateur a chargé la première requête). Par exemple, //your-app.com/somethingsera envoyé à l'application Rails, puis renvoyé à votre application React (le HTML / JS / CSS déjà chargé dans le navigateur), qui décidera de ce qu'il faut afficher à l'écran.
  • Considérations relatives à la création d'une application sur une seule page. Pas nécessaire pour ce tutoriel mais utile.
  • Modèles de conception React Component. Encore une fois, pas nécessaire mais utile.

Configuration requise

Pour info, voici ma configuration système. Ne pas dire que vous en avez besoin, mais quelque chose de similaire rendra l'expérience de ce didacticiel plus fluide.

  • macOS 10.13.6 (High Sierra)
  • Rubis 2.5.1
  • Rails 5.2.1 (et Bundler 1.16.6)
  • - bundler d'installation gem -v 1.16.6
  • Nœud 9.8.0

Enfin, passons au code!

Étape 1: Créez un nouveau projet Rails avec Webpack et React

Créez une nouvelle application Rails. J'ai nommé le mien rails-react-tutorial.

rails new rails-react-tutorial --webpack=react

Voir ici pour plus d'informations sur le --webpack=reactdrapeau introduit dans Rails 5.1.

Étape 2: Assurez-vous que les gemmes Webpacker et React-Rails sont installées

Vérifiez si les gemmes Webpacker et React-Rails sont dans votre fichierGemfile . Si les gemmes ne sont pas là, ajoutez-les:

Maintenant, exécutez ces commandes pour tout installer.

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 

Maintenant, exécutez rails server -p 3000 et visitez //localhost:3000pour vous assurer que notre projet fonctionne.

Astuce de pro n ° 1 : exécutez ./bin/webpack-dev-serverdans une fenêtre distincte pendant le codage pour que les modifications soient automatiquement créées et rechargent le navigateur.

Astuce Pro # 2 : Si vous obtenez cette erreur can’t activate sqlite3 (~> 1.3.6), already activated sqlite3–1.4.0, alors un dd gem ‘sqlite3’, ‘~>1.3.6 'à Gemfile. Voir ce lien pour plus d'informations.

Étape 3: Ajoutez une classe Controller et une Route à notre application Rails

Ajoutez un nouvel itinéraire à notre application Rails. Pour cet exemple, nous ajouterons un GET /v1/thingspoint de terminaison à config/routes.rb`.

Cette nouvelle route nécessitera un ThingsController. Créez un nouveau app/controllers/v1/things_controller.rbfichier. N'oubliez pas qu'il doit être dans le v1dossier car il appartient à notre API Rails.

Notre contrôleur Things renverra une réponse codée en dur pour GET /v1/things.

À ce stade, vous devriez pouvoir réexécuter rails server -p 3000et visiter //localhost:3000/v1/things.

Ensuite, nous allons créer un nouveau composant React.

Étape 4: Générer un nouveau composant React

Créez un composant HelloWorld React qui accepte un paramètre String nommé greetingen exécutant la commande suivante:

rails generate react:component HelloWorld greeting:string

Un fichier doit être créé: app/javascript/components/HelloWorld.js.

Étape 5: Utilisez notre composant HelloWorld

Pour utiliser et voir notre nouveau composant HelloWorld, nous avons besoin de 2 choses: créer une vue incorpore ce composant et ajouter une route pour pointer vers cette vue.

Pour créer une vue, créez le fichier app/views/static/index.html.erbet ajoutez les éléments suivants:

Pour notre nouvelle route, ajoutez la ligne suivante à notre routes.rbfichier et un StaticController vide pour le prendre en charge.

Ajoutez ceci à app/controllers/static_controller.rb:

Vous devriez maintenant être en mesure de réexécuter rails server -p 3000et de visiter //localhost:3000/pour voir votre nouveau composant React (n'oubliez pas de l'exécuter ./bin/webpack-dev-serverdans une fenêtre séparée pour que les modifications Javascript soient automatiquement emballées par le webpack).

Maintenant que nous avons un composant React qui rend dans notre vue, développons notre application pour prendre en charge plusieurs vues avec react-router.

Étape 6: Ajouter React-Router

Tout d'abord, exécutez cette commande pour ajouter react-router-dom, qui inclut et exporte tous react-routeret certains composants d'assistance supplémentaires pour la navigation Web. Plus d'infos ici.

npm install --save react-router-domyarn install

Cette commande devrait ajouter la ligne suivante à votre package.jsonfichier. Notez que 4.2.2 a été utilisé ici, mais votre version pourrait être différente.

Utilisons maintenant React Router pour créer des routes pour notre React Front-End.

Étape 6: Utilisation de React-Router

react-routernous permet de gérer toutes nos routes UI strictement avec Javascript. Cela signifie que nous aurons besoin d'un seul composant «App» qui encapsule l'ensemble de notre application. «App» utilisera également React-Router pour présenter le composant «Page» correct pour l'URL demandée.

Pour commencer, exécutez cette commande pour ajouter un composant d'application qui représentera l'ensemble de notre application frontale.

rails generate react:component App

Ensuite, ouvrez le fichier du composant React nouvellement créé app/javascript/components/App.jset ajoutez ce qui suit…

Maintenant, changez index.html.erbpour pointer vers notre nouveau composant App.

Enfin, modifiez votre routes.rbpour que Rails envoie toutes les demandes qui ne sont pas destinées à l'API à notre composant App (via StaticController#index).

Nous pouvons maintenant exécuter rails server -p 3000et visiter //localhost/et //localhost/hellovoir le fonctionnement de React-Router (n'oubliez pas d' ./bin/webpack-dev-serveractiver l'auto-webpacking).

Ensuite, nous devrons installer des dépendances supplémentaires avant de pouvoir connecter notre front-end React à notre API Rails.

Étape 7: Ajout de Redux, Sagas, Babel Polyfill et Axios

Ajoutons maintenant les bibliothèques Javascript suivantes pour notre front-end.

  • Redux pour gérer l'état global de notre application.
  • Babel-Polyfill pour activer des fonctionnalités Javascript sophistiquées qui autrement ne seraient pas disponibles sur les anciens navigateurs Web.
  • Resélectionnez et React-Redux pour faciliter le travail avec Redux.

Pour tout installer, exécutez ce qui suit:

npm install --save redux babel-polyfill reselect react-reduxyarn install

Nous allons maintenant utiliser ces outils pour configurer un magasin d'état Redux, puis ajouter des actions et des réducteurs pour l'utiliser.

Étape 8: Configurer Redux State Store

Dans cette étape, nous allons configurer le Redux State Store pour notre application avec le modèle suivant (nous ajouterons et supprimerons des «choses» dans les étapes suivantes).

{ "things": [ { "name": "...", "guid": "..." } ]}

Commencez par créer un configureStore.jsfichier. Cela initialisera notre boutique Redux.

Maintenant, importez et utilisez configureStore()dans le composant d'application pour créer un état Redux et le connecter à notre application.

Maintenant, vous avez Redux installé dans votre application! Ensuite, nous allons créer une action et un réducteur, et commencer à écrire et à lire à partir de notre état Redux.

Étape 9: Ajouter une action et un réducteur

Maintenant que l'application a un état Redux, nous allons ajouter unon> to HelloWorld that dispatches an Action (that we will define here) that will be received by the rootReducer().

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 on> to HelloWorld that dispatches a getThings() Action (from ./actions/index.js) on every click.

Original text


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):

  1. Dispatch the original Action object
  2. Make a call to our Rails API.
  3. 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!