Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React Redux et optimisations

React Redux et optimisations

Avatar for VincentCordobes

VincentCordobes

February 27, 2017
Tweet

More Decks by VincentCordobes

Other Decks in Programming

Transcript

  1. React Construction d’UIs Déclaratif • “A quoi l’application ressemble” à

    chaque instant Composants React • Un composant = une fonction ƛ 4 React Redux Optimisations Problèmes de perf. Quizz
  2. Stateless functional component 5 React Redux Optimisations Problèmes de perf.

    Quizz const Bonjour = (props) => ( <div>Bonjour {props.user}</div> )
  3. Classe ES6 6 React Redux Optimisations Problèmes de perf. Quizz

    class Bonjour extends React.Component { render() { return <div>Bonjour {this.props.user}</div> } }
  4. API d’un composant Un composant ‘fonction’ possède : • des

    props Un composant ‘classe’ possède en plus : • un state • une méthode render • des méthodes liée à son cycle de vie : – componentDidMount – componentWillReceiveProps – etc.. 7 React Redux Optimisations Problèmes de perf. Quizz
  5. Dessiner dans le DOM 8 React Redux Optimisations Problèmes de

    perf. Quizz ReactDOM.render( <Bonjour user="Vincent" />, document.getElementById('root') )
  6. 2 types de composants Container → logique de l’application Presentational

    → Vue 10 React Redux Optimisations Problèmes de perf. Quizz
  7. React 11 React Redux Optimisations Problèmes de perf. Quizz class

    TrackList extends React.Component { state = { tracks: [] } componentDidMount() { axios.get('/tracks') .then(response => response.data) .then(tracks => this.setState({ tracks })) .catch(handleError); } render() { return ( <ul> {this.state.tracks.map(track => ( <li>{track}</li> ))} </ul> ✘ Pas terrible oui il manque les fermetures des blocs !
  8. Container component 12 React Redux Optimisations Problèmes de perf. Quizz

    // LOgic goes here!! // we have completely separated our logic and our view class TrackListContainer extends React.Component { state = { tracks: [] } componentDidMount() { axios.get('/tracks') .then(response => response.data) .then(tracks => this.setState({ tracks })) .catch(handleError); } render() { // This is our view // and the `tracks` props is like our ViewModel return <TrackList tracks={this.state.tracks} /> } } ✔ cool
  9. Presentational component 13 React Redux Optimisations Problèmes de perf. Quizz

    // here is our view const TrackList = ({ tracks }) => ( <ul> {tracks.map(track => ( <li>{track}</li> ))} </ul> ) ✔ cool
  10. Flux : Redux ‣ Gérer le state d’une application ‣

    Implémentation la plus populaire ✨ 17 React Redux Optimisations Problèmes de perf. Quizz
  11. 3 principes ‣ Une seule source de vérité : le

    state ‣ Le state est immutable ‣ reducers : fonctions pures pour MAJ le state 18 React Redux Optimisations Problèmes de perf. Quizz View Store Reducer Actions Actions
  12. Actions ‣ Object décrivant la modification a apporter au state

    19 React Redux Optimisations Problèmes de perf. Quizz { type: 'CHANGE_NAME', payload: 'Vince' }
  13. Création des actions (Action creators) ‣ Actions réutilisables ‣ Tests

    20 React Redux Optimisations Problèmes de perf. Quizz function changeName(name) { return { type: 'CHANGE_NAME', payload: name } }
  14. Reducer Spécifie la manière dont le state doit se mettre

    à jour Fonction pure → ne doit jamais : – Modifier directement ses arguments – Avoir des effets de bords – Appeler des fonctions impures 21 React Redux Optimisations Problèmes de perf. Quizz (previousState, action) → nextState
  15. Reducer 22 React Redux Optimisations Problèmes de perf. Quizz ✘

    Incorrect function user(state = {}, action) { switch (action.type) { case 'CHANGE_NAME': state.name = action.name return state; default: return state; } } INTERDIT !!
  16. Reducer 23 React Redux Optimisations Problèmes de perf. Quizz function

    user(state = {}, action) { switch (action.type) { case 'CHANGE_NAME': return { ...state, name: action.name, } default: return state; } } ✔ correct
  17. Store ‣ Contient le state de l’application ‣ Permet l’accès

    au state via getState() ‣ Permet la mise à jour du state via dispatch(action) ‣ Permet l’abonnement des composants via subscribe(listener) → composants notifiés lorsque le state subit une modification 24 React Redux Optimisations Problèmes de perf. Quizz
  18. Async/await 25 React Redux Optimisations Problèmes de perf. Quizz function

    whatsMyName(): Promise<string> { return Promise.resolve('Vincent'); } async function foo(): Promise<number> { const myName = await whatsMyName(); console.log(myName); return 42; }
  19. Actions asynchrones 26 React Redux Optimisations Problèmes de perf. Quizz

    Middleware Redux-thunk • Traiter les actions étant des fonctions function whatIsMyName() { return async (dispatch, getState) => { dispatch(fetchNameRequest()); try { const res = await fetch( 'http://vincent.cordobes/name'); const name = await res.json(); dispatch(fetchNameSuccess(name)); } catch (err) { dispatch(fetchNameError(err)); } }
  20. Synoptique Redux 27 React Redux Optimisations Problèmes de perf. Quizz

    Presentational Components Props connect State Store Selectors Compute derived data from state Reducers dispatch Actions data & callback functions Update the state Props Container components Lifecycle hooks ex: ComponentWillMount = () => fetchData()
  21. Composants “container” ‣ Responsables de la manière dont “les choses”

    fonctionnent ‣ Sont souvent stateful et servent de sources de données ‣ “Dispatchent” les actions flux ‣ Transmettent des données et comportements aux “composant de pres”. via leur props ‣ Peuvent contenir des composants “présentation” et “container” • Ne contiennent jamais d’éléments du DOM ni de styles!! ‣ Peuvent être générés par connect() 28 React Redux Optimisations Problèmes de perf. Quizz source : https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.6oac6zpqz
  22. Composants de présentation ‣ Responsables de la manière dont “les

    choses” apparaissent sur l’interface ‣ Peuvent contenir des composants “présentation” et “container” • possèdent souvent des éléments du DOM et sont stylisés ‣ Indépendants du reste de l’application ‣ Ne spécifient pas la manière dont les données sont chargés ou modifiées ‣ Reçoivent les données et les callback exclusivement via leurs props ‣ Possède uniquement un state si celui-ci concerne l’UI (et non des data) ‣ Souvent écrits sous forme de fonctions 29 React Redux Optimisations Problèmes de perf. Quizz source : https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.6oac6zpqz
  23. 34 React Redux Optimisations Problèmes de perf. Quizz const i

    = 42 const j = ‘toto’ const titi = new Person() const moi = { firstname: ‘Vincent’, lastname: ‘Cordobes } Stack Heap Rappel référence i: 42 j: ‘toto’ Person object titi(ref) moi(ref) object (firstname, lastname)
  24. Mutable 35 React Redux Optimisations Problèmes de perf. Quizz Stack

    Heap moi object (firstname, lastname) previousMoi const moi = { firstname: ‘Vincent’, lastname: ‘Cordobes’, } const previousMoi = moi moi.firstname = ‘Toto’ previousMoi === moi // true
  25. Immutable Un object ne peut pas changer ! Si changement

    → nouvelle référence 36 React Redux Optimisations Problèmes de perf. Quizz const moi = someAPIForImmutable.create({ firstname: ‘Vincent’, lastname: ‘Cordobes’, }) const moi1 = moi.set(‘firstname’, ‘Toto’) moi === moi1 // false Immutable
  26. Optimisation possible ! 37 React Redux Optimisations Problèmes de perf.

    Quizz setState ShouldComponentUpdate: False shallowEqual des props !
  27. React → Pure.Component 38 React Redux Optimisations Problèmes de perf.

    Quizz React.PureComponent is exactly like React.Component but implements shouldComponentUpdate() with a shallow prop and state comparison. “ ‒ Facebook https://facebook.github.io/react/docs/react-api.html#react.purecomponent
  28. Connect 40 React Redux Optimisations Problèmes de perf. Quizz Composant

    Composant VDOM return return TrackItem Connect(TrackItem) Container
  29. Connect 41 React Redux Optimisations Problèmes de perf. Quizz Composant

    Composant VDOM return return TrackItem Connect(TrackItem) componentDidMount() { this.store.subscribe(…) } ... componentWillUnmount() { this.unsubscribe(…) } shouldComponentUpdate() { … }
  30. Shallow Equal 42 React Redux Optimisations Problèmes de perf. Quizz

    export default function shallowEqual(objA, objB) { if (objA === objB) { return true } const keysA = Object.keys(objA) const keysB = Object.keys(objB) if (keysA.length !== keysB.length) { return false } // Test for A's keys different from B. const hasOwn = Object.prototype.hasOwnProperty for (let i = 0; i < keysA.length; i++) { if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) { return false } } return true }
  31. === 43 React Redux Optimisations Problèmes de perf. Quizz export

    default function shallowEqual(objA, objB) { if (objA === objB) { return true } const keysA = Object.keys(objA) const keysB = Object.keys(objB) if (keysA.length !== keysB.length) { return false } // Test for A's keys different from B. const hasOwn = Object.prototype.hasOwnProperty for (let i = 0; i < keysA.length; i++) { if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) { return false } } return true } Comparaison superficielle objA et obj B Desfois qu’il y ait une propriété en moins ou en plus Comparaison des propriétés de A et B
  32. Selectors 44 React Redux Optimisations Problèmes de perf. Quizz State

    Component Render Props filteredData = data.filter(company) return (filteredData) connect
  33. Selectors 45 React Redux Optimisations Problèmes de perf. Quizz State

    data company Component Render Props return (filteredData) Selectors Compute derived data from state connect data.filter(company)
  34. Exemple 47 React Redux Optimisations Problèmes de perf. Quizz D’yer

    Mak’er - Led Zeppelin More than a feeling - Boston Dire Strait - Sultans of Swing Alt-j - intro True Strength - John Dreamer True Strength - John Dreamer mp3 mp3 My music app mp3 mp3 mp3 mp3 TrackList TrackItem
  35. Sources des ‘render’ possibles React: • setState • Mon parent

    se render Redux: • Abonné à une partie du state ayant subit un changement 48 React Redux Optimisations Problèmes de perf. Quizz
  36. Redux Trouver l’origine du problème Abonné à une partie du

    state ayant subit un changement → Une props a changé! 50 React Redux Optimisations Problèmes de perf. Quizz const findWhichPropsHasADifferentRef = (currProps, nextProps) => { const res = []; Object.keys(currProps).forEach((key) => { if (currProps[key] !== nextProps[key]) { res.push(key); } }); return res; } non… sa référence!!
  37. Donc ‣ Ne pas exposer des composants à un state

    dont ils ne sont pas concernés • Plus votre composant grossis et plus le risque augmente ‣ Ne passer à un composant seulement les informations utiles à ce composant ‣ Utiliser des sélecteurs mémoisés 51 React Redux Optimisations Problèmes de perf. Quizz
  38. QUIZ 53 React Redux Optimisations Problèmes de perf. Quizz track

    track track tracks state music travel car boat playlists
  39. Render de A? 54 React Redux Optimisations Problèmes de perf.

    Quizz track track track tracks state music travel car boat playlists Composant A const mapStateToProps = (state) => ({ data: state, boat: state.travel.boat, car: state.travel.car, }); Connected Oui !
  40. Render de B? 55 React Redux Optimisations Problèmes de perf.

    Quizz track track track tracks state music travel car boat playlists Composant B const mapStateToProps = (state) => ({ playlist: state.music.playlists, myTravelPlan: { boat: state.travel.boat, car: state.travel.car, } }); Connected Oui !
  41. Render de B? 56 React Redux Optimisations Problèmes de perf.

    Quizz Solution : const mapStateToProps = (state) => ({ playlist: getPlaylist(state), myTravelPlan: getMyTravelPlan(state), }); const getMyTravelPlan = createSelector( state => state.travel.boat, state => state.travel.car, (boat, car) => ({ boat, car }) ); const mapStateToProps = (state) => ({ playlist: state.music.playlists, myTravelPlan: { boat: state.travel.boat, car: state.travel.car, } }); Oui ! Par exemple avec reselect On mémoise la création de l’object
  42. Petit tips reselect 57 React Redux Optimisations Problèmes de perf.

    Quizz const mapStateToProps = (state) => ({ playlist: getPlaylist(state), myTravelPlan: getMyTravelPlan(state), }); const getMyTravelPlan = createSelector( state => state.travel.boat, state => state.travel.car, (boat, car) => ({ boat, car }) ); const mapStateToProps = createStructuredSelector({ playlist: getPlaylist, myTravelPlan: myTravelPlan, }); const mapStateToProps = (state) => ({ playlist: getPlaylist(state), myTravelPlan: getMyTravelPlan(state), });
  43. Render de C ? 58 React Redux Optimisations Problèmes de

    perf. Quizz track track track tracks state music travel car boat playlists Composant C const mapStateToProps = (state) => ({ boat: state.boat, firstTracks: getFirstTracks(state.music.tracks, 10), }); const getFirstTracks = (tracks, nbTracks) => tracks.slice(0, nbTracks); Connected Oui !
  44. Render de C ? 59 React Redux Optimisations Problèmes de

    perf. Quizz Solution : const getFirstTracks = createSelector( state => state.music.tracks, (tracks) => tracks.slice(0, nbTracks); ); Oui ! On mémoise le traitements const mapStateToProps = (state) => ({ boat: state.boat, firstTracks: getFirstTracks(state.music.tracks, 10), }); const getFirstTracks = (tracks, nbTracks) => tracks.slice(0, nbTracks);
  45. Render de D ? 60 React Redux Optimisations Problèmes de

    perf. Quizz track #1 track #2 track #3 tracks state music travel car boat playlists Composant D const getVeryComplexeStuff(state, props) = createSelector( (state, { id }) => state.music.tracks[id] (track) => computeSomeStuffs(state, id) ) const mapStateToProps = (state, props) => ({ complexStuff: getVeryComplexeStuff(state, props), }); connect(mapStateToProps)(D) Oui ! ⚠ cache de taille 1
  46. Render de D ? 61 React Redux Optimisations Problèmes de

    perf. Quizz Solution : const makeGetVeryComplexeStuff = () => createSelector((state, { id }) => computeSomeStuffs(state, id)) const makeMapStateToProps = () => (state, props) => { const getVeryComplexeStuff = makeGetVeryComplexeStuff(); return { complexStuff: getVeryComplexeStuff(state, props), } } Oui ! const getVeryComplexeStuff(state, props) = createSelector( (state, { id }) => computeSomeStuffs(state, id) ) const mapStateToProps = (state, props) => ({ complexStuff: getVeryComplexeStuff(state, props), });
  47. Render de D ? 62 React Redux Optimisations Problèmes de

    perf. Quizz Solution : const makeComplexeSelector = () => createSelector((state, { id }) => computeSomeStuffs(state, id)) const makeMapStateToProps = () => (state, props) => { const getVeryComplexeStuff = makeComplexeSelector(); return { complexStuff: getVeryComplexeStuff(state, props), } } Oui ! connect(makeMapStateToProps)(D)
  48. Références • React - https://facebook.github.io/react • Redux doc - http://redux.js.org

    • reselect doc - https://github.com/reactjs/reselect • Smart and dumb component - https://medium.com/@dan_abramov/smart- and-dumb-components-7ca2f9a7c7d0#.h6rxn85kl • Async await proposal - https://tc39.github.io/ecmascript-asyncawait 63