Redux: La doc `combineReducers` n'explique pas comment deviner quelle partie de l'état passer au réducteur

Créé le 8 août 2015  ·  7Commentaires  ·  Source: reduxjs/redux

Le nouveau document CombineReducers est ok, mais il n'explique pas que vous devez nommer le réducteur comme la partie de l'état qu'il gère.

docs

Commentaire le plus utile

Merci pour vos retours, c'est très précieux.

je tiens à souligner que

Les conventions font partie de l'API

n'est pas vraiment vrai.

Nous devrions probablement éviter import * dans la documentation parce que les gens supposent que cela fait partie intégrante de l'API alors que ce n'est pas du tout, et c'est juste un raccourci pratique que j'utilise.

Les noms de fonction n'ont d'importance qu'en raison de la façon dont ES6 export et import * as fonctionnent.

Au fait, je ne sais toujours pas comment passer une sous-partie d'état au réducteur. Dois-je camelCase les rejoindre ou quelque chose comme ça ? state={owner : {name : 'John'} } → fonction d'exportation ownerName(state = [], action) ?

Non :-). Ce n'est pas une API magique. combineReducers(object) combine plusieurs réducteurs en un seul et transmet des parties de l'état à ses valeurs par les clés que vous fournissez. Cela ne fait qu'exactement un niveau de profondeur. Il n'y a pas de « magie de l'arbre entier ». A vous de diviser un réducteur en plusieurs fonctions :

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using combineReducers
let store = createStore(reducer);

Ils n'ont même pas d'importance si vous utilisez combineReducers helper tant que vous créez l'objet vous -

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

Vous pouvez le faire plusieurs fois.

Avant de:

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

function processA(state, action) {
  return {
    // Because you call them!
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using the helper
let store = createStore(reducer);

Tu vois? Ce sont juste des fonctions qui appellent des fonctions. Pas de "trucs profonds" magiques.
Et vous pouvez également utiliser combineReducers plusieurs fois :

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

/*
function processA(state, action) {
  return {
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
*/
let processA = combineReducers({
  somePart: processSomePartOfA,
  otherPart: doSomethingWithOtherPartOfA
});

function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

La seule partie où les noms de fonction importent est lorsque vous utilisez export + import * as pour « obtenir » un objet que vous passez à combineReducers parce que _c'est comme ça que import * fonctionne_ ! Il met les choses dans l'objet en fonction de leurs clés d'exportation.

Je pense que ma plus grande erreur ici est de supposer que le lecteur est familier avec les exportations nommées.

Tous les 7 commentaires

Il le dit un peu si vous le lisez complètement, sans sauter :

Le réducteur résultant appelle chaque réducteur enfant et rassemble leurs résultats dans un seul objet d'état. La forme de l'objet d'état correspond aux clés des réducteurs passés.

Mais je suis d'accord que cela doit être plus important, car les gens manquent souvent cette phrase.
Est-ce que les changements de #399 vous aideraient ?

Je préférerais moins d'informatique, note explicite sur cette convention juste après l'exemple :

Notez que les réducteurs sont nommés todos et counter -- exactement comme les parties de l'état que nous leur transmettons.

Pour passer une partie de l'état au réducteur, Redux utilise _convention_ -- le réducteur doit être nommé exactement comme une partie de l'état que vous souhaitez lui passer.

Je pense que #399 est bien mais c'est une explication pour les _utilisateurs de Flux_. J'arrive à Redux frais du bateau. Une certaine forme de mon texte serait plus utile pour les développeurs JavaScript occasionnels.

L'idée importante ici est la suivante : les conventions font partie de l'API . C'est tout aussi important pour createRedux , createDispatcher et toute autre fonction API. Indiquez toujours explicitement les conventions car elles font partie de l'API.

Au fait, je ne sais toujours pas comment passer une sous-partie d'état au réducteur. Dois-je camelCase les rejoindre ou quelque chose comme ça ? state={owner: {name: 'John'} }export function ownerName(state = [], action) ?

Merci pour vos retours, c'est très précieux.

je tiens à souligner que

Les conventions font partie de l'API

n'est pas vraiment vrai.

Nous devrions probablement éviter import * dans la documentation parce que les gens supposent que cela fait partie intégrante de l'API alors que ce n'est pas du tout, et c'est juste un raccourci pratique que j'utilise.

Les noms de fonction n'ont d'importance qu'en raison de la façon dont ES6 export et import * as fonctionnent.

Au fait, je ne sais toujours pas comment passer une sous-partie d'état au réducteur. Dois-je camelCase les rejoindre ou quelque chose comme ça ? state={owner : {name : 'John'} } → fonction d'exportation ownerName(state = [], action) ?

Non :-). Ce n'est pas une API magique. combineReducers(object) combine plusieurs réducteurs en un seul et transmet des parties de l'état à ses valeurs par les clés que vous fournissez. Cela ne fait qu'exactement un niveau de profondeur. Il n'y a pas de « magie de l'arbre entier ». A vous de diviser un réducteur en plusieurs fonctions :

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using combineReducers
let store = createStore(reducer);

Ils n'ont même pas d'importance si vous utilisez combineReducers helper tant que vous créez l'objet vous -

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

Vous pouvez le faire plusieurs fois.

Avant de:

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

function processA(state, action) {
  return {
    // Because you call them!
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using the helper
let store = createStore(reducer);

Tu vois? Ce sont juste des fonctions qui appellent des fonctions. Pas de "trucs profonds" magiques.
Et vous pouvez également utiliser combineReducers plusieurs fois :

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

/*
function processA(state, action) {
  return {
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
*/
let processA = combineReducers({
  somePart: processSomePartOfA,
  otherPart: doSomethingWithOtherPartOfA
});

function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

La seule partie où les noms de fonction importent est lorsque vous utilisez export + import * as pour « obtenir » un objet que vous passez à combineReducers parce que _c'est comme ça que import * fonctionne_ ! Il met les choses dans l'objet en fonction de leurs clés d'exportation.

Je pense que ma plus grande erreur ici est de supposer que le lecteur est familier avec les exportations nommées.

Je pense que ma plus grande erreur ici est de supposer que le lecteur est familier avec les exportations nommées.

Je pense que, en supposant que le lecteur soit familier avec ES6, c'est un peu exagéré. Mais c'est ce qui pousse les gens à apprendre et à comprendre ce genre de choses. C'est donc en fait une bonne chose lorsque la lecture est en avance sur les connaissances et l'expérience du lecteur.

Nous modifions les exemples pour appeler explicitement combineReducers dans reducers/index donc j'espère que cela aura plus de sens à partir de maintenant : https://github.com/gaearon/redux/pull/473

Clôture, car cela semble être mieux traité dans les documents actuels.
Et nous n'utilisons plus import * dans les documents non plus.

Pensez-vous vraiment qu'intégrer un comportement implicite comme celui-ci est une bonne pratique de codage ?

Pour moi, cela brouille le code et combineReducer ne devrait pas exister, cela ajoute une étape d'abstraction inutile et complexifie le processus.

Lorsque vous écrivez un framework, une caractéristique importante comme celle-ci doit être facilement compréhensible, ce n'est évidemment pas le cas, par exemple le sentiment "magique".

PS : je viens de la documentation officielle Redux : "Ce n'est pas magique"

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

cloudfroster picture cloudfroster  ·  3Commentaires

amorphius picture amorphius  ·  3Commentaires

ramakay picture ramakay  ·  3Commentaires

CellOcean picture CellOcean  ·  3Commentaires

jbri7357 picture jbri7357  ·  3Commentaires