Redux, Rematch, et plus si affinités 1/63

@jutanguy

https://www.welcometothejungle.co/companies/valwin/jobs

(Progressive) Web App Profil utilisateur Objets métier

ProgressiveBig Web App

“Local state is fine” – Dan Abramov

Local state #NoRedux

Use the Context, Luke

Limites du state local

https://redux.js.org

Les trois principes de Redux Unique source de vérité État en lecture seule Les changements sont faits avec des fonctions pures Concepts fondamentaux Actions Reducers Store

Action Objet avec une clé type, décrivant un ou des changements passés.

Action creator

  1. export const addTodo = (text) => ({ type: 'TODO_ADDED', id: newUUID(), text: text }) Fonction qui retourne une action.

Reducer Fonction permettant d'aggréger ce qui s'est passé dans un état

Reducer

Store Encapsule l'état Fournit les actions pour interroger l'état et dispatcher les actions

Store

import { createStore } from 'redux'; import todoReducer, { addTodo } from './reducers'; const store = createStore(todoReducer, window.STATE_FROM_SERVER) console.log(store.getState()) store.dispatch(addTodo('Tester redux')) console.log(store.getState())

Store 1 2 3 4 5 6 7 const store = createStore(todoReducer) console.log(store.getState()) store.dispatch(addTodo('Tester redux')) console.log(store.getState()) Powered by RunKit Node 10  help  run

Middleware

Logger Middleware 1 2 3 4 5 6 7 8 9 10 11 12 const logger = store => next => action => { console.group(action.type); console.log('action: ', action); const result = next(action); console.log('next state: ', store.getState()); console.groupEnd(); return result; } const store = createStore(todoReducer, applyMiddleware(logger)) store.dispatch(addTodo('Tester redux')) Powered by RunKit Node 10  help  run

Utilisation avec react

import import import import import React from 'react' { render } from 'react-dom' { Provider } from 'react-redux' createStore from './store' App from './components/App' const store = createStore(); render( <Provider store={store}> <App />

app.js

New Devtools Redux > Simple

Redux recap

“You might not need Redux” – Dan Abramov

Redux === Code applicatif

Redux & Tests Meetup 2: “Ceintures, bretelles et stratégies de test” par Sylvain Bannier

Actions creators & Tests

Reducers & Tests

  1. import reducer, { addTodo } from './reducers'; 2. 3. describe('reducer', () => { 4. it('comes with an initial state', () => { 5. expect(reducer(undefined)).toMatchSnapshot(); 6. }); 7. it('should apply actions', () => { 8. const newState = reducer(undefined, addTodo("Tester le reducer")); 9. expect(newState).toHaveLength(1); 10. }); 11. });

Reducers & Tests 2

  1. import reducer, { addTodo } from './reducers'; 2. import diff from 'snapshot-diff'; 3. 4. 5. describe('reducer', () => { 6. it('comes with an initial state', () => { 7. expect(reducer(undefined)).toMatchSnapshot(); 8. }); 9. it('should apply actions', () => { 10. const initialState = reducer(undefined); 11. const newState = reducer(initialState, addTodo("Tester le reducer")); 12. expect(diff(initialState, newState)).toMatchSnapshot(); 13 })

Gestion des effets Comment faire des appels à des APIs ?

utilisation de redux-thunk

redux-thunk

                        1. 13 function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } } }; return next(action); const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware;

redux-saga Je n'ai toujours pas saisi les générateurs en js

redux-api-middleware

  1. import { RSAA } from redux-api-middleware; // RSAA = '@@redux-api-middleware/RSAA' 2. 3. { 4. [RSAA]: { 5. endpoint: 'http://www.example.com/api/users', 6. method: 'GET', 7. types: ['REQUEST', 'SUCCESS', 'FAILURE'] 8. } 9. } 10.

Request

  1. { 2. "type": "REQUEST" 3. }

Response

  1. { 2. "type": "SUCCESS", 3. "payload": { 4. "users": [ 5. { "id": 1, "name": "John Doe" }, 6. { "id": 2, "name": "Jane Doe" }, 7. ] 8. } 9. }

Problèmes avec redux-api-middleware On perd le contrôle du flot d'actions Comment faire

Ma préférence: redux-thunk

Advanced Redux

Normalisation de l'état

Response

Normalizr

import { normalize, schema } from 'normalizr'; const user = new schema.Entity('users'); const comment = new schema.Entity('comments', { commenter: user, }); const article = new schema.Entity('articles', { author: user, comments: [comment],

1 2 3 4 5 6 7 8 9 10 11 12 const user = new schema.Entity('users'); const comment = new schema.Entity('comments', { commenter: user, }); const article = new schema.Entity('articles', { author: user, comments: [comment], }); const normalizedData = normalize(data, article); Powered by RunKit Node 10  help  run

Architecture #protip La distinction entre container et component n'est pas forcément utile à refléter dans le filesystem

Convention de nommage https://hackernoon.com/structuring-projects-and-naming-componentsin-react-1261b6e18d76

Better naming

src ├─ components │ ├─ User │ │ ├─ Form │ │ │ ├─ Form.jsx │ │ │ └─ Form.css │ │ └─ List.jsx │ └─ UI │ └─ screens ├─ User

Les gros fichiers ne sont pas nécessairement mauvais

Dan Abramov @dan_abramov Okay, I give in. I wrote a guide on the most scalable file structure for React projects. I’m using it every day. Best part: it works for Vue projects too. Hope it’s helpful! react-filestructure.surge.sh 5,268 6:30 PM - Aug 8, 2018 1,764 people are talking about this

move files around until it feels right

Frederic Barthelemy @fbartho · Aug 8, 2018 Replying to @dan_abramov I think beginners don’t know how anything feels, and want a guideline for where to start so they can focus on harder concepts, faster. (* me as a React beginner 8 months ago looking at those same articles) Dan Abramov @dan_abramov It is a guideline though. It means literally “start by putting everything in one file; when it feels like it’s annoying, start splitting them up; what THAT gets annoying, maybe add some folders”. 461 6:43 PM - Aug 8, 2018 95 people are talking about this

Redux ducks

redux/modules/todo.js

Redux est verbeux C'est normal, il n'a pas été conçu pour être concis Best practices Boilerplates

Rematch

Rematch = Redux + Best practices https://hackernoon.com/redesigning-redux-b2baee8b8a38 redéclaration des types d'actions action creators thunks création du store mapDispatchToProps

redux duck

                                    1. 19 import newUUID from 'uuid/v4'; // Action types const ADDED = 'TODO_ADDED'; // Reducer export default function reducer(state = [], action){ switch(action.type){ case 'TODO_ADDED': return [...state, {id: action.id, text: action.text}]; default: return state; } } // Action creators export const todoAdded = (text, id) => ({ type: ADDED, id: id, text: text }); export const addTodo = (text) => dispatch => axios

Rematch

New Devtools Redux > Rematch

Merci https://www.welcometothejungle.co/companies/valwin/jobs

Liens https://redux.js.org https://rematch.gitbooks.io/rematch