#CestFacile : Ajouter Redux après un create-react-app

Dans la droite lignée du post que j’ai balancé à chaud hier, je me suis dis qu’une petite série de posts assez courts ne serait pas du luxe pour quiconque a envie un jour de se lancer dans l’aventure.

L’idée de ces posts, c’est d’aller tout de suite à l’essentiel. Si vous souhaitez connaitre l’intérêt de Redux (et des autres librairies pour lesquelles je posterai ici), les Internets sont déjà bien fournis.

On commence donc par l’ajout de Redux dans une application React créée avec create-react-app.

Pas d’obligation en terme d’arborescence

Avant tout, sachez que vous pouvez organiser vos fichiers de la façon qui vous convient le plus. Il n’y a pas de règle universelle. On essaiera quand même de respecter la nomenclature des fichiers de façon à avoir un peu compréhension.

Moi, je pars sur une arborescence telle qu’Alexis Mangin la propose. Du moins je m’en inspire.

Parce que ça me parle, je trouve que ça a du sens, et pour avoir connu des projets où on a commencé à partir d’un tuto pour se retrouver quelques mois plus tard vers une arbo presque incompréhensible et nécessitant pas mal de refacto, et bien autant avoir quelque chose qui aura encore du sens dans 6 mois.

Pour ce post, on va donc avoir une arbo à peu près comme celle-ci :

Mes actions et reducers sont localisés dans Services. La configuration de mon store et mon rootReducer sont dans Store.

Moi ca me convient, donc ca ne conviendra sans doute pas à d’autres. A vous de voir 🙂

Let’s go

On commence par installer redux et react-redux

yarn add react-redux redux

Une fois que c’est fait, on commence par créer notre rootReducer :

import {combineReducers} from 'redux'
import stuff from '../Services/Stuff/reducer'
const rootReducer = combineReducers({
  stuff
})

export default rootReducer

Dans Store/rootReducer.js

On collera nos reducers au fur et à mesure de leur création dans combineReducers. Ici, on a juste « stuff »

Maintenant on créé notre reducer et par la même occasion nos actions et actionTypes:

import * as types from './actionTypes'

export const doSomething = (something) =>({
  type: types.DO_SOMETHING,
  something
})

Dans Services/Stuff/actions.js

L’idée d’importer les actions avec un alias, ca nous évitera de devoir gérer l’import de tout plein d’actions qui vont venir nous polluer visuellement.   Attention, ici, je fais un return implicite.
Vous pouvez également faire quelque chose comme ça :
export const doSomething = (something) => {
  return {
     type: types.DO_SOMETHING,
     something
  }
}
On créé ensuite notre actionTypes :
export const DO_SOMETHING = 'DO_SOMETHING'

Dans /Services/Stuff/actionTypes.js

Puis on créé notre reducer :
import * as types from './actionTypes'
import initialState from '../../Store/initialState'

let stuff = (state = initialState.stuff, action) => {

  switch(action.type){
    case types.DO_SOMETHING:
      let newState = [...state]
      newState.push(action.something)
      return newState

    default:
      return state;
    }
}

export default stuff;
Dans Services/Stuff/reducer.js
On renvoi une nouvelle version du state dans laquelle on push notre nouvelle entrée.
Maintenant on va créer notre initialState :
const initialState = {
  stuff: []
}
export default initialState
Dans Store/initialState.js
A ce stade on a juste une array stuff. Dans certains tutos, vous verrez parfois que l’initialState est déclaré au niveau de chaque reducers, ce qui est peut être une bonne chose pour la lisibilité, mais devient un peu overkill quand vous souhaitez passer votre initialState afin d’écrire vos tests unitaires.
Maintenant on configure notre store :
import {createStore, applyMiddleware} from 'redux'
import rootReducer from './rootReducer'
const configureStore = () => {
  return {
    ...createStore(rootReducer)
  }
}

export default configureStore;
Dans Store/configureStore.js
On importe notre rootReducer pour créer notre store. Ici, on ajoute pas de Middleware pour l’instant (on verra ca dans un autre post à propos de Redux Saga et Redux Thunk.

Implémentation dans React

On vient de voir comment créer le boilerplate autour de Redux. Fondamentalement c’est quelque chose que vous faites une seule fois pour chaque projet et sur lequel vous ne revenez que rarement, en dehors du fait d’ajouter des reducers ou des middlewares.
On va maintenant implémenter Redux dans React. On part sur quelque chose de simple, basique, que l’on fera évoluer petit à petit par la suite.
On commence par créer notre provider au sein de notre index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './Scenes/App/App';
import registerServiceWorker from './registerServiceWorker';
import {Provider} from 'react-redux'
import configureStore from './Store/configureStore'

const store = configureStore();

ReactDOM.render(
  <Providerstore={store}>
    <App />
  </Provider>,
document.getElementById('root'));

registerServiceWorker();

Dans index.js

On y est presque, maintenant on a plus qu’à passer notre state et nos actions à nos props dans nos containers :

 

See the Pen NyOvmL by daibai (@Daibai) on CodePen.

Ici, on balance directement un dispatch au mount du component histoire de vérifier que ça fonctionne bien.

J’importe toutes les actions de l’action creator Stuff pour les injecter dans un mapDispatchToProps. C’est un peu crade, mais rien ne vous empêche d’importer ce que vous voulez avec plus de précision.

Ce sera tout, merci de votre compréhension.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *