Front End Developer 

@MeKimak

React

Chips & Tricks

React Ecosystem

fetch

Webpack

dev: npm start

var path = require('path');
var express = require('express');
var webpack = require('webpack');
var config = require('./webpack.config.dev');

var app = express();
var compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));

app.get('*/*', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.listen(8080, 'localhost', function(err) {
  if (err) {
    console.log(err);
    return;
  }

  console.log('Listening at http://localhost:8080');
});
  "start": "node devServer.js"

Webpack hot reload

NODE_ENV=production

 warning(
    'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
    'This means that you are running a slower development build of Redux. ' +
    'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
    'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
    'to ensure you have the correct code for your production build.'
  )
"build": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js",

prod: npm build

web_modules/

  • Structure "à plat"
  • Facilité de nommage
  • "Easy refactoring" 

css loader for webpack

//webpack.config.js 
var ExtractTextPlugin = require("extract-text-webpack-plugin"); 
 

module.exports = {
 plugins: [
    new ExtractTextPlugin("styles.css")
 ],

//...

 module: {
    loaders: [
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract(
          "style-loader",
          "css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]"
         ),
        include: path.join(__dirname, 'web_modules')
      }
    ]
  },
};

localIndentName

"css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]"
//web_modules/Input/index.js

import styles from "./index.css";

export default class Input extends Component {

  render() {
    return (
      <input type="text" className={styles.input}></input>
    )
  }
}

//web_modules/Input/index.css

.input{
    margin: 10px;
}


//Browser DOM
<input type="text" class="index__input___2ohV8"></input>


Bye bye... INLINE STYLE !

Hello Css Loader.

Cool !

Et on peux importer du    

        ?

Euh... oui mais on va faire mieux !

Postprocessor > PreProcessor

PostCss

PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more."

Plugin Autoprefixer

:fullscreen a {
    display: flex
}
:-webkit-full-screen a {
    display: -webkit-box;
    display: -webkit-flex;
    display: flex
}
:-moz-full-screen a {
    display: flex
}
:-ms-fullscreen a {
    display: -ms-flexbox;
    display: flex
}
:fullscreen a {
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex
}

compiles to:

Plugin Custom Properties

:root {
  --color: red;
}

div {
  color: var(--color);
}
div {
  color: red;
}

compiles to:

Plugin Custom Media

@custom-media --small-viewport (max-width: 30em);

@media (--small-viewport) {
  /* styles for small viewport */
}
@media (max-width: 30em) {
  /* styles for small viewport */
}

compiles to:

Plugin Calc

:root {
  --main-font-size: 16px;
}

body {
  font-size: var(--main-font-size);
}

h1 {
  font-size: calc(var(--main-font-size) * 2);
  height: calc(100px - 2em);
}
body {
  font-size: 16px
}

h1 {
  font-size: 32px;
  height: calc(100px - 2em)
}

compiles to:

Webpack config PostCss

//webpack.config.js 

module.exports = {
    
  postcss: [
    require("autoprefixer"),
    require("postcss-custom-properties"),    
    require("postcss-custom-media"),
    require("postcss-calc")
  ],

};
"css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader"

Des variables globales ?

//webpack.config.js 

var webpackPostcssTools = require("webpack-postcss-tools");
var globalMap = webpackPostcssTools.makeVarMap("web_modules/app/css/global.css");

module.exports = {
    
  postcss: [
    require("autoprefixer"),
    require("postcss-custom-properties")({
    require("postcss-custom-media"),		
        variables: globalMap.vars
    }),
    require("postcss-custom-media")({
        extensions: globalMap.media
    }),
  ],

};

package.json

  "babel": {
    "presets": [
      "react",
      "es2015"
      //"stage-0"
    ],
    "plugins": [
      "transform-decorators-legacy",
      "transform-object-rest-spread",
      "transform-class-properties",
      "transform-export-extensions",
      "syntax-trailing-function-commas"
    ],
    "env": {
      "development": {
        "presets": [
          "react-hmre"
        ]
      }
    }
  }

.babelrc

Decorators

// npm install babel-plugin-transform-decorators-legacy --save-dev
// "plugins": ["transform-decorators-legacy"]

@connect(
    (state) => ({
        artists : state.artists
    }),
    (dispatch) => ({
        getArtists : (value) => dispatch(getArtists(value)),
    })
)
export default class Artists extends Component {

Object Rest/Spread

// npm install babel-plugin-transform-object-rest-spread --save-dev
// "plugins": ["syntax-object-rest-spread"]

let a = {v:1, w:2};
let b = {x:3, y:4, z:5}

console.log({...a, ...b}) // {"v":1,"w":2,"x":3,"y":4,"z":5} 

Class Properties

// npm install babel-plugin-transform-class-properties --save-dev
// "plugins": ["transform-class-properties"]


//Without plugin
class ReactCounter extends React.Component {
  constructor(props) { // boilerplate
    super(props); // boilerplate

    this.state = {
      count: 0
    };
  }
}

//With plugin
class ReactCounter extends React.Component {
  state = {
    count: 0
  };
}

Export extensions 

// npm install babel-plugin-transform-export-extensions --save-dev
// "plugins": ["transform-export-extensions"]


import React, {PropTypes, Component} from "react"

import v, {x, y as w} from "module"

Syntax trailing function commas

// npm install babel-plugin-syntax-trailing-function-commas --save-dev
// "plugins": ["syntax-trailing-function-commas"]


 1: function clownPuppiesEverywhere(
 2:   param1, // updated to add a comma
 3:   param2 // updated to add new parameter
 5: ) { /* ... */ }


 1: function clownPuppiesEverywhere(
 2:   param1,
 3:   param2, // Next parameter that's added only has to add a new line, not modify this line
 5: ) { /* ... */ }

fetch

Une requête AJAX hier

(Asynchronous JavaScript and XML)

Une requête AJAX aujourd'hui

https://fetch.spec.whatwg.org/

Can i use ?

fetch polyfill

//webpack.config.js 
//$ npm install exports-loader --save-dev
 

module.exports = {

 plugins: [
   new webpack.ProvidePlugin({
       fetch: "exports?self.fetch!whatwg-fetch"
   })
 ],

};

Limitation de fetch ? Abort.

Utilisez superagent si besoin...

(superagent-bluebird-promise)

react-router

Params & optional

Multiple component

Architecture

STORE: "Single source of truth"

Reducer

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

<- ACTION

<- STATE

Sub-Reducer

Sub-Reducer

import { combineReducers } from "redux"

import settings from "./settings"
import geoblocking from "./geoblocking"
import feedback from "./feedback"
import storage from "./storage"

export default combineReducers ({
    settings,
    geoblocking,
    feedback,
    storage
});

npm deep-freeze

npm deep-freeze

"Beginner advice"

connect logique

"Beginner advice"

presentation component !=connected component

"Beginner advice"

connect performance

The end.

React Chips & Tricks

By Mickael Dumand

React Chips & Tricks

  • 4,413