Génération dynamique d'apps avec

React

Bonsoir !

David Blavier

Florian Rival

@bam_lab

@One2Team_France

@FlorianRival

CTO @

Architecte-développeur @

 

Agile Project & Portfolio Management

 

 

Telco

Retail

New Product Development

 

 

Contexte

Contexte

Client

Besoin spécifique

App One2Team

Consultant

One2Team

Paramétrage

L'architecture

React

Paramétrage

Composants

Actions

Reducers

Store

{
   list: [...],
   documents: [...]
}
{
   type: "NEW_DOCUMENT_ADDED",
   document: {title: "Hello"}
}
function(state, action) {
   return {list: [action.document]}
}
export default class DocumentPicker extends Component {












  render() {
    return 
      <div>
        <span>{this.props.title}</span>
        ...
        <button onClick={() => dispatchActions(this.props.onPick)}>
          Pick
        </button>
      </div>
  }
}

Composants modulaire

  static propTypes = {
    list: PropTypes.string.isRequired,
    onInit: PropTypes.action.isRequired,
    title: PropTypes.string.isRequired,
    selection : PropTypes.string.isRequired,
    onPick: PropTypes.action.isRequired,
  };

Composant modulaires

Recevoir une action :

Recevoir une partie du state :

Utiliser cette partie du state :

PropTypes.action
static contextTypes = {
    state: PropTypes.object.isRequired,
}
const listName = this.props.list
this.context.state[listName]
static propTypes = {
    list: PropTypes.string.isRequired,
}

Actions et reducers Redux

Exemple action

Exemple reducer

export default makeReducer(initialState, {
  // On request success, update the store with more elements of the list
  [FETCH_MORE_LIST_SUCCESS]: (state, action) => {
    return {
      ...state,
      status: Status.loaded,
      items: [
        ...state.items,
        ...action.items,
      ],
    }
  },
})
export const load = makeActionCreator(
  FETCH_INIT_LIST_SUCCESS,
  (items = []) => ({ items })
)

Comment composer ces éléments pour créer une app ?

Fichier de configuration

Description déclarative des :

  • Composants
  • Actions
  • Reducers

Chargé au démarrage après identification du client

{ //App specific configuration:
    "views": [{...}],
    "actions": [{...}],
    "reducers": [{...}]
}

Fichier de configuration

views: [{
    "id": "contacts_view_subpopup", //View name
    "component": "DocumentPicker", //JS class to use
    "props": {
        "list": "contacts_reducer_step0_document_document", //part of the state
        "onInit": ["contacts_action_step0_fetch_document_document"], //Action names
        "title": "Entite Client", //Arbitrary prop
        "selection": "contacts_reducer_step0_document_selection", //part of the state
        "onPick": ["contacts_action_step0_update_document"], //Action names
    }
}]

Déclaration des composants :

Fichier de configuration

{
    "id": "contacts_action_step0_update_document",
    "target": "contacts_reducer_step0_document_list", //Reducer name
    "component": "DocumentList", //The JS class to use
    "action": "postUpdates",
}

Déclaration des actions :

{
    "id": "contacts_reducer_step0_document_list",
    "component": "DocumentList" //The JS class to use
}

Déclaration des reducers :

Instancier les vues

On associe les vues de la configuration à leur composant

const createViews = (template) => { //template is the configuration file
  return template.views.reduce((views, v) => {
    const Component = getFactory("views", v.component)
    views[id] = {
      Component,
      props,
    }

    return views
  }, {})
}

Instancier les vues

export default class Navigation extends Component {
  render() {
    const current = getCurrentViewid(state.navigation)
    const { Component, props } = views[current] ? views[current] : {}
    
    return
      <div className={ styles.container }>
        <NavigationBar {...} />
        <Component {...props} />
      </div>

Composant racine qui crée la vue courante

export default class Form extends Component {
  render() {
    const { views } = this.context

    return this.props.formFields.map((formField) => {
      const { Component, props } = views[formField.viewId]
      return <Component {...props} />
    }
  }
}

Les composants peuvent eux meme en créer d'autres

Instancier les actions et reducers

Création de tous les reducers et des actions au démarrage de l'app de la meme manière que précedemment :

const createActions = (template) => {
  ... //Retourne la liste des actions crées
}

const createReducers = (template) => {
  ... //Retourne la liste des reducers crées
}

Ce qui vous sauve la vie

Devtools redux

  • Inspection du state
  • Vérification des actions

redux-devtools

Ce qui vous sauve la vie

Devtools React

react-devtools

Inspection de l'arbre des composants

Ce qui vous sauve la vie

Hot loader

Edition ultra efficace du style d'un composant

react-transform-hmr

Merci ! :)

Génération dynamiques d'apps avec React, Redux et Cordova

By Florian Rival

Génération dynamiques d'apps avec React, Redux et Cordova

Talk at ReactJS and React Native Paris (French)

  • 2,593