JAVASCRIPT EN FUSION

REACT

ChtiJS #10 - 5/02/2015

UN MOT SUR MOI

  • Tom Panier, aka neemzy
  • Développeur web chez CGI
  • Fait du PHP chez Auchan E-Commerce France
  • Aime aussi le JS et le front-end

QUOI ?

REACT

  • Librairie de Facebook "pour fabriquer des IHMs"
  • V dans MVC

JAVASCRIPT ATOMIQUE

  • Orienté objet
  • Notion de composant (on y reviendra)

DU COUP ?

  • Permet de structurer le code JS front-end
  • Plus lisible, plus maintenable, plus performant

EXEMPLE RAPIDE

// helloWorld.js

window.HelloWorld = React.createClass({
    render: function() {
        return React.createElement(
            'div',
            { className: 'hello-world' },
            'Hello world!'
        );
    }
});

EXEMPLE RAPIDE

<div id="content"></div>

<script src="helloWorld.js"></script>
<script>
    React.render(
        React.createElement(window.HelloWorld),
        document.getElementById('content')
    );
</script>

JSX TO THE RESCUE

var HelloWorld = React.createClass({
    render: function() {
        return (
            <div className="hello-world">Hello world!</div>
        );
    }
});

React.render(
    React.createElement(HelloWorld),
    document.getElementById('content')
);

Du HTML

dans le JS ?

Mais c'est dég...

LOL
NOOB

JSX TO THE RESCUE

  • Le JSX n'est pas du HTML !
  • Séparation des rôles plutôt que des langages
  • Le markup appartient au composant

JSX TO THE RESCUE

  • avantages : plus lisible, plus représentatif du HTML généré
  • inconvénient : compilation nécessaire

WORKFLOW REACT/JSX AVEC GULP

var gulp = require('gulp'),
    env = require('gulp-env'),
    browserify = require('gulp-browserify');

env({ vars: { NODE_ENV: 'production' } }); // ou 'development'

gulp.task('jsx', function () {
    gulp.src('path/to/app.js')
        .pipe(browserify({
            insertGlobals: false,
            transform: ['reactify'],
            extensions: ['.jsx']
        }))
        .pipe(gulp.dest('path/to/compiled/'));
});
npm install react gulp-browserify reactify gulp-env --save-dev

L'ALTERNATIVE : REACT-NO-JSX

var HelloWorld = React.createClass({
    render: function() {
        return (
            ['div', { className: 'hello-world' }, 'Hello world!']
        );
    }
});

React.render(
    React.createElement(HelloWorld),
    document.getElementById('content')
);

COMMENT ?

PROPS

var HelloWorld = React.createClass({
    render: function() {
        return (
            <div className="hello-world">
                Hello {this.props.name}!
            </div>
        );
    }
});

React.render(
    React.createElement(HelloWorld, { name: 'Tom' }),
    document.getElementById('content')
);

PROPS

  • Propriétés immuables d'un composant
  • Configuration, données d'un composant parent

ÉLéMENTS IMBRIQUÉS

Oscar de la meilleure blague 1962

ÉLÉMENTS IMBRIQUÉS

var SuperUsefulApp = React.createClass({
    render: function() {
        return (
            <HelloWorld name="Tom" />
        );
    }
});

React.render(
    React.createElement(SuperUsefulApp),
    document.getElementById('content')
);

ÉLÉMENTS IMBRIQUÉS

  • Hiérarchie de composants / d'éléments HTML
  • Forme un tout : l'application / le module

STATE

var SuperUsefulApp = React.createClass({
    getInitialState: function() {
        return { name: '' };
    },

    handleInput: function(event) {
        this.setState({ name: event.target.value });
    },

    render: function() {
        return (
            <div className="super-useful-app">
                <input type="text" onInput={this.handleInput} />
                <HelloWorld name={this.state.name} />
            </div>
        );
    }
});

STATE

  • État d'un composant à un instant t
  • Changé par des évènements (la plupart du temps)
  • Un changement rappelle                             (reactive programming)

render()

BEST PRACTICES

  • Garder autant de composants que possible stateless
  • Utiliser les props pour communiquer de parent vers enfant

DE L'AJAX ?

Oscar de la meilleure blague 2006

DE L'AJAX ?

var SuperUsefulApp = React.createClass({
    getInitialState: function() {
        return { name: '' };
    },

    fetchNameFromServer: function() {
        return new Promise(function (resolve, reject) {
            taLibAjaxFavorite({
                url: this.props.url,
                method: 'GET',
                success: function(name) {
                    resolve(name);
                }
            });
        }.bind(this));
    },

DE L'AJAX ?

    updateName: function() {
        this.fetchNameFromServer()
            .then(function (name) {
                this.setState({ name: name });
            }.bind(this));
    },

    componentWillMount: function() {
        // on récupère le nom tout de suite
        this.updateName();

        // on le met à jour toutes les secondes
        // ça serait mieux avec une websocket (vrai realtime)
        this.setInterval(this.updateName, 1000);
    },

DE L'AJAX ?

    render: function() {
        return (
            <HelloWorld name={this.state.name} />
        );
    }
});

WHAT U GONNA DO?

TESTING

  • Oui, du code front, ça se teste
  • Plusieurs possibilités

PARENTHÈSE : LES REFS

render: function() {
    return (
        <div class="super-useful-app">
            <input type="text"
             onInput={this.handleInput}
             ref="input" />
            <HelloWorld name={this.state.name} />
        </div>
    );
}
  • Permet d'identifier un élément/composant enfant

TESTING : PAR DÉFAUT

var testUtils = React.addons.TestUtils,
    testApp = testUtils.renderIntoDocument(<SuperUsefulApp />),
    input = testApp.refs.input.getDOMNode();

expect(input.value).to.equal('');

testUtils.Simulate.click(input);
testUtils.Simulate.change(input, { target: { value: 'Johnny' } });
testUtils.Simulate.keyDown(input, { key: 'Enter' });
  • Utilise Jest
  • Plutôt verbeux

TESTING : JASMINE-REACT

describe('Components.HelloWorld', function() {
    this.reactSuite({ type: HelloWorld });

    it('should render', function() {
        expect(subject.isMounted()).toBeTruthy();
    });
});
  • Utilise Jasmine (NO SHIT)

TESTING : REACT-PAGE-OBJECTS

var testApp = new PageObject(<SuperUsefulApp />);

expect(testApp.input.value).to.equal('');

testApp.input.click();
testApp.input.value = 'Johnny';
testApp.input.keyDown('Enter');
  • Sucre syntaxique pour les outils de base
  • Moins verbeux (du coup)

POURQUOI ?

LE WEB ÉVOLUE

  • Web 3.0 : Internet des objets
  • Montée en puissance de JavaScript
  • Notion de composant (on y arrive)

LE WEB ÉVOLUE

$('button').on('click', function () { /* ... */ });
var nom = prompt('Quel est votre nom ?');
var SomeClass = function() {};

SomeClass.prototype.sayCheese = function() {
    return 'Cheese!';
};

var instance = new SomeClass();
console.log(instance.sayCheese());

WEB COMPONENTS

  • Briques autonomes et réutilisables (HTML, CSS, JS...)
  • Permettent de déclarer des éléments custom
  • Nouvelle façon de penser le développement web
  • React : un pas vers le futur ?

WEB COMPONENTS

  • 2009 : il y a un plugin jQuery pour ça
  • 2012 : il y a une directive Angular pour ça
  • 2015 : il y a une mixin React pour ça
  • 2018 : il y aura un web component pour ça

"REACT VS ANGULAR"

  • Les deux ne sont pas opposés !
  • Angular : application MVC complète (routing...)
  • React : V dans MVC
  • On peut même les utiliser ensemble (ngReact)

"REACT VS ANGULAR" : PERFORMANCE

  • Two-way data binding : lourdeur exponentielle
  • One-way data binding : on garde le contrôle
  • Shadow DOM : re-rendering efficace

"REACT VS JQUERY"

  • Pas le même rôle non plus
  • React fait une partie du boulot... mieux
  • The right tool for the right job plutôt qu'un couteau suisse

COMPATIBILITÉ

  • Tous les vrais navigateurs, obviously
  • IE >= 8 (avec polyfills)

LE MOT DE LA FIN

  • Le JS c'est bon, mangez-en...
  • ...mais mettez-vous à la diète de jQuery
  • React : simplicité et qualité pour un besoin peu complexe
  • Pour une appli full JS : Angular, Ember... ou Flux !

Et c'est

pas fin...

TG

EFFET DÉMO INCOMING

EN BONUS, BANDE DE GALOPINS

NEEMZY... NEEMZY EVERYWHERE

MERCI DE VOTRE ATTENTION !

Des questions ?

React : JavaScript en fusion

By Tom Panier

React : JavaScript en fusion

ChtiJS #10 - 5/02/2015

  • 4,666