@bam_lab
@One2Team_France
@FlorianRival
CTO @
Architecte-développeur @
Agile Project & Portfolio Management
Telco
Retail
New Product Development
Client
Besoin spécifique
App One2Team
Consultant
One2Team
Paramétrage
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>
}
}
static propTypes = {
list: PropTypes.string.isRequired,
onInit: PropTypes.action.isRequired,
title: PropTypes.string.isRequired,
selection : PropTypes.string.isRequired,
onPick: PropTypes.action.isRequired,
};
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,
}
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 })
)
Description déclarative des :
Chargé au démarrage après identification du client
{ //App specific configuration:
"views": [{...}],
"actions": [{...}],
"reducers": [{...}]
}
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 :
{
"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 :
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
}, {})
}
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
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
}
redux-devtools
react-devtools
Inspection de l'arbre des composants
Edition ultra efficace du style d'un composant
react-transform-hmr