React Documentation

Why was React developed?

  • Complexity of two-way data binding
  • Bad UX from using "cascading updates" of DOM tree
  • A lot of data on a page changing over time
  • Complexity of Facebook's UI architecture
  • Shift from MVC mentality

No complex two-way data flow

 

  • Uses simple one-way reactive data flow
  • Easier to understand than two-way binding
  • Uses less code

React is fast!

  • Real DOM is slow
  • JavaScript is fast
  • Using virtual DOM objects enables fast batch updates to real DOM, with great productivity gains over frequent cascading updates of DOM tree

React dev tools

  • React Chrome extension makes debugging  so much easier

React is nothing but the view

  • No events
  • No XHR
  • No data / models
  • No promises / deferreds
  • No idea how to add all of the above

Component

 

Components are self-contained reusable building blocks of web application.

React components are basically just idempotent functions (same input produces same output).

They describe your UI at any point in time, just like a server-rendered app.

Component

  • Created using React.createClass()
  • The only required method is render()
  • Inserted into DOM using React.renderComponent()
var React = require('react'),
    SimpleView = React.createClass({
        render: function () {
            return <h1><strong>Example 1:</strong> A simple component</h1>;
        }
    });

React.renderComponent(SimpleView(), document.getElementById('example'));

 

    return <div>
        <AnotherComponent foo={someProp} model={this.props.model} />
    </div>;
}

State

Virtual DOM

  • The virtual DOM is used for efficient re-rendering of the DOM
  • React aims to re-render the virtual tree only when the state changes
  • Uses 2 virtual trees (new and previous) to find differences and batch update real DOM
  • Observes data changes (setState) and does dirty-checking to know when to re-render component
  • Whenever possible, does not update entire component in real DOM - only computes a patch operation that updates part of the DOM

Read tutos

 

https://learnreact.com/

https://reactcheatsheet.com/

https://reactpatterns.com

http://slides.com/alexanderfarennikov/react-js-fundamentals/fullscreen#/20

 

Tricks

this.props.onSearchTermChange(term);

Why React ?

- Need flexibility

- Prefer big ecosystems

- Do not want to bother with choosing among various packages

- Are fond of JS

- Work with a medium-sized team, but it might grow

- Like Vue.js but its ecosystem is too limited for your project.

Tutos

Prez

 

Redux Constraints

 

  • Single State Tree
  • Actions Describe Updates
  • Reducers Apply Updates
  • Log actions and states
  • Find the bad state
  • Check the action
  • Fix the reducer
  • Write a test

Debug Workflow

 

Reducers

(state, action) => state

Les props envoyées à StudentsList permettent la connexion à Redux.

A chaque changement d'état à appliquer, une fonction embarquée dans une propriété est déclenchée depuis un composant (Student par exemple). Le lien entre cette fonction à appeler et cette propriété est faite dans le container. Le container permet donc le dispatch vers l'action adéquate, action présente dans le fichier actions.js. Cette action contient un type (qui doit être unique). Redux appelle les reducers attachés au store. Le reducer contenant le même type que l'action appelée va exécuter sa fonction pure correspondante. Le changement d'état va déclencher un affichage dans la vue. C'est le fameux one-way data binding de Redux.

Simples Examples of Redux

The whole state of your app is stored in an object tree inside a single store.
The only way to change the state tree is to emit an action, an object describing what happened.
To specify how the actions transform the state tree, you write pure reducers.

 

That's it!

/**
* This is a reducer, a pure function with (state, action) => state signature.
* It describes how an action transforms the state into the next state.
*
* The shape of the state is up to you: it can be a primitive, an array, an object,
* or even an Immutable.js data structure. The only important part is that you should
* not mutate the state object, but return a new object if the state changes.
*
* In this example, we use a `switch` statement and strings, but you can use a helper that
* follows a different convention (such as function maps) if it makes sense for your
* project.
*/

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state - 1
  default:
    return state
  }
}

// Create a Redux store holding the state of your app.
// Its API is { subscribe, dispatch, getState }.
let store = createStore(counter)

 

// You can use subscribe() to update the UI in response to state changes. However it can also be handy to persist the current state in the localStorage.
store.subscribe(() =>
  console.log(store.getState())
)

// The actions can be serialized, logged or stored and later replayed.
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1

Containers

 

Le container est le dernier aspect pour lier les composants et Redux. Le composant StudentsList étant le parent des autres composants de gestion des élèves (Student et StudentForm), c'est lui qui sera lié à Redux. Dans ce cas, Student est un composant de présentation, c'est-à-dire qu'il ne fera qu'afficher des informations transmises par un conteneur. Ce conteneur, sous-entendu conteneur de composant de présentation, sera StudentsList, le seul à être lié directement à Redux.

+

 

 

Que fait ce conteneur ? Il possède deux fonctions Redux :

  • mapStateToProps : il prend l'état (ou une partie de l'état en fonction du besoin) de l'application (ici l'objet contenant les élèves) et le transmet à StudentsList sous forme de propriété. C'est pour cela que dans StudentsList, on reçoit students dans les propriétés : const { students, ... } = props;

 

  • mapDispatchToProps : cette fonction passe des fonctions sous forme de propriétés à StudentsList. C'est la suite des propriétés envoyées à StudentsList : const { ..., toggleForm, updateForm, addStudent, deleteStudent } = props;Elle prend en paramère la fonction dispatch de Redux, chargée d'informer le store qu'un changement d'état se produit et qu'il faut donc appeler l'action adéquate (contenue dans le créateur d'actions - actions.js). La fonction mapDispatchToProps se charge donc de faire correspondre chaque propriété passée à StudentsLists à la fonction issue de action.js (qui lui même appelera la bonne fonction dans le reducer). Par exemple, au clic à la création d'un élève, la propriété addStudent contient une référence à la fonction addStudent de action.js. Ce lien est fait ici, dans mapDispatchToProps. Ainsi, à la soumission du formulaire de création d'un élève, la propriété addStudent de StudentsList est appelée. C'est en fait la fonction addStudent de actions.js qui sera déclenchée (et in fine, le cas "ADD_STUDENT" du reducer, permettant le changement réel de l'état de l'appliction, permettant d'augmenter l'objet gérant les élèves d'un enregistrement).

Dans une application web moderne, nous gérons des tas d'éléments comme :

  • la connexion utilisateur
  • des formulaires
  • des droits utilisateur sur des pages
  • l'ajout, la modification et l'affichage de données (le fameux CRUD)
  • ...

Ces éléments sont contenus dans des objets au sein d'une application React. Comment savoir dans toutes les pages de l'application si :

  • un utilisateur est connecté
  • un formulaire est validé
  • l'utilisateur en cours a le droit d'accès à la page
  • la modification d'une donnée en base est bien répercutée en front pour être réactualisée
  • .... ?
  •  

Cette architecture est structurée ainsi:

  • Actions – Des méthodes qui vont passer des données au Dispatcher
  • Dispatcher – Reçoit les actions et renvoit des charges utiles (payloads) à des fonctions de rappel (callbacks) enregistrées au préalable
  • Stores – Contient l'état de l'application et la logique des fonctions de rappel enregistrées dans le Dispatcher
  • Controller Views – Des composants React qui chargent l'état depuis le ou les Stores et le passent à des composants enfants.
const reducers = {
  reducer,
  form: formReducer,
}
const reduc = combineReducers(reducers);
const store = createStore(reduc);

Les deux dernières lignes sont nécessaires pour que Redux fonctionne : avec plusieurs reducers, il est nécessaire de les combiner. Ensuite, quelque soit le nombre de reducers, il faut créer un store, ce qui va conserver l'état des objets au sein de l'application (tant que le navigateur est ouvert en tout cas, à moins de gérer la persistance mais cela va au-delà de notre sujet).

+

 

 

On utilise ici la bibliothèque Immutable.js pour respecter la philosophie Redux qui ne modifie pas un enregistrement à chaque fois mais le recrée permettant des comparaisons très rapides entre objets puisqu'elle se fera sur la référence de l'objet plutôt que sur l'objet lui-même

Cela devient intéressant sur de gros objets avec plusieurs niveaux d'imbrication. Ce n'est donc pas obligatoire pour notre simple application. Mais c'est un concept important à connaître.

import Immutable, { List, Map } from 'immutable';

export const students = List([
  Map({ id: 1465171631163, firstName: 'Jean', lastName: 'Borotra', level: '6e', average: '10', isVisible: false, isUpdated: false }),
  Map({ id: 1465171646328, firstName: 'Jacques', lastName: 'Brugnon', level: '5e', average: '19', isVisible: false, isUpdated: false }),
  Map({ id: 1465171723584, firstName: 'Henri', lastName: 'Cochet', level: '3e', average: '14', isVisible: false, isUpdated: false }),
  Map({ id: 1465171659936, firstName: 'René', lastName: 'Lacoste', level: '6e', average: '8', isVisible: false, isUpdated: false }),
  Map({ id: 1465171707368, firstName: 'Suzanne', lastName: 'Lenglen', level: '6e', average: '15', isVisible: false, isUpdated: false }),
]);

Le principe du reducer est de réagir à des actions pour produire un nouvel état dans l'application. Ce seront donc des fonctions pures, sans effet de bord (side effect, par exemple des appels à une API externe) et qui vont aussi utiliser l'immutabilité pour recréer un état plutôt que de modifier celui existant. D'où l'intérêt d'utiliser Immutable.js (même si non obligatoire comme précisé plus haut).

+

 

 

Text

Environement Setup

React Part 1

By Julien Boyer

React Part 1

  • 948