Redux: Série de screencasts Redux sur Egghead

Créé le 24 nov. 2015  ·  69Commentaires  ·  Source: reduxjs/redux

Si vous suivez le référentiel Redux mais ne vous y êtes pas encore plongé, ou si vous êtes confus au sujet de certains de ses aspects fondamentaux, vous serez heureux d'apprendre qu'Egghead vient de publier ma série Getting Started with Redux .

Il couvre les mêmes sujets que la partie « Bases » de la documentation, mais, espérons-le, approfondit un peu et vous assure de _vraiment_ comprendre les principes fondamentaux de Redux.

Je prévois de créer plus de contenu sur Redux sur Egghead, cette fois, pour les abonnés uniquement. Il comportera des sujets plus avancés. Si vous avez des suggestions particulières, faites-le moi savoir dans ce fil!

feedback wanted

Commentaire le plus utile

@markerikson merci d'avoir

Remarque : pour plus de commodité, je vais utiliser thunk pour représenter une approche middleware abritée de l'async, qu'il s'agisse en fait de redux-thunk ou de redux-promise, ou autre.

Votre couche d'interface utilisateur ne fait que connecter les interactions des utilisateurs aux gestionnaires. Lorsque quelqu'un clique sur un bouton, votre interface utilisateur est configurée pour appeler _some_ handler. Souvent, le composant reçoit ces gestionnaires en tant qu'accessoires --- peut-être un créateur d'action lié, par exemple. L'interface utilisateur ne sait pas ce qui se passe lorsqu'elle appelle un gestionnaire --- elle l'appelle simplement.

Cela ne fait aucune différence pour la couche d'interface utilisateur que le "gestionnaire" envoie une fonction (à gérer par un middleware) ou s'il exécute un appel asynchrone et _then_ envoie une action simple --- l'interface utilisateur est complètement agnostique (ou du moins, elle _peut_ être agnostique)

Une grande partie de votre "application" se trouve dans ces "gestionnaires", que vous utilisiez des thunks ou non. Dans une application de réaction/redux typique, ces "gestionnaires" sont souvent des créateurs d'action. Vous pouvez écrire tous vos trucs asynchrones sous forme de thunks et les envoyer. Ou, vous pouvez écrire tous vos trucs asynchrones sous forme de fonctions qui acceptent dispatch comme argument. Du point de vue du composant, c'est soit someHandler(dispatch) OU dispatch(someHandler()) , ou dans le cas des créateurs d'action liés transmis de plus haut, c'est juste someHandler() dans les deux cas. Vous pouvez créer une version de bindActionCreators qui masquerait complètement cette différence par rapport à la couche d'interface utilisateur.

Si vous me donnez une application de réaction/redux écrite avec des créateurs d'action utilisant redux-thunk, je pourrais complètement remplacer redux-thunk et utiliser une approche non middleware sans changer _fondamentalement_ la couche d'interface utilisateur. (remarque : je ne précise pas où/comment vous injectez getState , mais je pense que c'est un détail mineur ici).

Par conséquent, j'ai du mal à accepter que la distinction entre "intérieur" et "extérieur" soit "niveau application" ou "niveau UI".

J'apprécie la discussion, et j'espère que je n'ai pas l'air négatif.

Tous les 69 commentaires

:+1:

  1. État du composant local par rapport à l'état global
  2. Action gérée par plusieurs réducteurs vs relation action-réducteur 1 à 1
  3. Gestion des chaînes d'action (en particulier celles asynchrones), lorsque la deuxième action doit être déclenchée juste après la fin de la première.
  4. Techniques d'optimisation pour éviter un renouvellement inutile (actions de dosage, resélection etc.).

:+1:

Je viens de regarder les 16 premiers épisodes de la série et je pense qu'ils sont une excellente ressource que nous utiliserons probablement pour la formation interne dans l'entreprise pour laquelle je travaille. Cependant, le fait que vous n'ayez jamais utilisé que des objets simples et gelé pour votre arbre d'état, et que vous n'utilisiez ou ne vous référiez jamais à des bibliothèques immuables comme

Ce serait formidable de connaître votre opinion à ce sujet.

Le fait de jeter Immutable dans le mélange confondrait les débutants qui auraient besoin d'apprendre à faire la différence entre Redux et l'API Immutable, pourraient supposer qu'Immutable est requis, etc. C'est cependant une bonne idée pour quelques leçons avancées !

Le fait de jeter Immutable dans le mélange confondrait les débutants qui auraient besoin d'apprendre à faire la différence entre Redux et l'API Immutable, pourraient supposer qu'Immutable est requis, etc. C'est cependant une bonne idée pour quelques leçons avancées !

D'accord, c'est logique. C'est juste bon de savoir ce que vous pensez de cette décision :-).

Ce que @smashercosmo a dit :+1:

Tests unitaires. TDD.

Ce que @cateland a dit :+1:

Je dois dire que je suis très impressionné par vos compétences, étant capable de créer d'excellentes bibliothèques js avec une documentation complète et des didacticiels concis de cette manière.

Après avoir visionné toutes les vidéos, j'ai un tas de commentaires sur les vidéos spécifiques que je vais envoyer par courrier. La conclusion est que c'est bien plus qu'une introduction à Redux. Vous couvrez les pratiques de code et l'architecture des composants et plus encore. C'est vraiment vraiment génial et très pédagogique. Je pense que les vidéos peuvent être divisées en trois groupes cependant. Redux basic, redux dans les coulisses et redux avec react.

Pour les prochaines vidéos, j'aimerais voir moins réagir sur des concepts spécifiques et plus sur les actions et les tests asynchrones.

Remarquablement bien fait, continuez comme ça ! :)

Dans la vidéo 21, vous notez que le composant TodoApp n'a plus besoin d'être une classe, il peut s'agir d'une fonction. Ce serait formidable si vous pouviez expliquer comment vous êtes arrivé à cette réalisation – Pourquoi est-ce un candidat approprié pour être un composant fonctionnel, et quel avantage cela donne-t-il ?

C'est tellement bon.

L'élément 3 de la liste de @smashercosmo est quelque chose que j'aimerais également savoir.

ce que @wpannell a dit ! Tests unitaires/TDD !

J'adorerais aussi voir des vidéos sur les sujets abordés dans les documents avancés.

Qu'est-ce qui vous intéresse en particulier en ce qui concerne les tests unitaires ?
Les leçons 5, 11, 12 donnent une idée de la façon de tester les réducteurs unitairement.

...C'est une bonne question. Le processus changerait-il beaucoup lorsqu'il s'agit de tests de moka ?

Pas vraiment. Mais je suppose que c'est un bon sujet pour une série de leçons avancées. Réducteurs de tests unitaires, créateurs d'actions, composants, etc.

Tout d'abord, de superbes vidéos. Je comprends déjà le redux mais c'était rafraîchissant.
Si vous créez des vidéos plus avancées, puis-je suggérer des actions/intergiciels asynchrones.
Ne pensez pas que les tests unitaires ont vraiment besoin d'une couverture. Vous pouvez simplement appeler vos fonctions réductrices et affirmer sur elles ?

Oui, je suppose que ce n'est vraiment pas grand-chose d'autre que d'envelopper les expect dans des tests moka. :pouces vers le haut:

Heureusement, tout est si simple !

Immuabilité avec les hachages d'ID d'objet (par exemple [post._id]: {...post} ).

Je me repose trop sur une fonction reduce pour prendre un tableau d'entités API et produire un hachage d'ID avec. Je sais que normalizr gérera une partie de cela, mais j'aimerais des vidéos similaires aux vidéos EggheadIO où vous nous emmènerez du point A au point B. Ce n'est pas uniquement une chose basée sur Redux, mais elle est fortement liée.

@raquelxmoss

Dans la vidéo 21, vous notez que le composant TodoApp n'a plus besoin d'être une classe, il peut s'agir d'une fonction. Ce serait formidable si vous pouviez expliquer comment vous êtes arrivé à cette réalisation – Pourquoi est-ce un candidat approprié pour être un composant fonctionnel, et quel avantage cela donne-t-il ?

C'était en fait une planification de cours bâclée de ma part. Je n'ai réalisé que trop tard que j'aurais pu en faire un composant fonctionnel dès le départ. L'avantage d'utiliser des fonctions par rapport aux classes est la simplicité, alors faites-le quand vous le pouvez. Fondamentalement, si vous n'avez pas besoin de hooks de cycle de vie comme componentDidMount ou state, utilisez des composants fonctionnels.

Je trouverais une leçon sur la façon dont nous pouvons diviser ces morceaux de code en une structure de répertoire réelle pour être utile. Je sais que tant que tout est là, ça va probablement fonctionner, mais peut-être que les conventions de nommage des dossiers recommandées (composant / conteneur / magasin / réducteur, etc.), quels types de fichiers vont dans quel dossier, etc. seraient bien.

J'aimerais aussi une composition de réducteur avancée.

Réutiliser des composants complexes (composés d'un ou de plusieurs réducteurs, d'un ensemble d'actions, de créateurs d'actions, accédant peut-être à une API côté serveur, plusieurs composants React - comme redux-form, mais plus spécifiques à une application réelle). Cela inclut également l'organisation d'une structure de répertoires modulaire.

J'ai tout regardé, très bien ! J'ai apprécié l'utilisation de la syntaxe ES6/7 ( Object.assign -like), les composants de la fonction React 0.14 et en évitant les choses immuables.

Peut-être une vidéo expliquant l'architecture de code recommandée.

Et mettre à jour la doc pour utiliser les syntaxes ES6/7 ? (les relations publiques sont-elles les bienvenues dans cette direction ?)

Tests unitaires, création d'API Middleware, OAuth/un certain type d'authentification utilisateur avec Redux, utilisation d'Immutable avec redux (comment le configurer, meilleures pratiques, etc.)

Cette série constitue une excellente introduction à Redux, à l'état de l'atome unique et aux philosophies associées. Je pense que vous avez fait un bon travail en vous concentrant sur les principes de base tout en évitant d'induire une surcharge cognitive. L'environnement dans lequel vous avez travaillé est également facilement reproductible, ce qui rend la partie pratique d'autant plus accessible.

@gaearon Que pensez-vous de la structuration des actions dans les exemples de vidéos en tant que { type: string, payload: Object } herbe dès le début ? Je parle de l'exemple de liste de compteurs, où la charge utile est placée sur l'objet d'action lui-même ; { type: string, index: number } . Cela ressemble à un anti-modèle pour moi.

Que pensez-vous de la structuration des actions dans les exemples de vidéos en tant que {type: string, payload: Object } standard en herbe dès le début ? Je parle de l'exemple de liste de compteurs, où la charge utile est placée sur l'objet d'action lui-même ; { type : chaîne, index : nombre }. Cela ressemble à un anti-modèle pour moi.

Ce n'est en aucun cas un anti-modèle. C'est un objet d'action normal. FSA c'est bien mais c'est une _convention_. Rien dans Redux lui-même ne dépend ou ne bénéficie de cette convention, nous ne voulons donc pas l'appliquer.

Les gens pensaient toutes sortes de choses magiques à propos de payload , source dans la documentation originale de Flux. Ils ont copié aveuglément ces choses sans comprendre pourquoi elles existent et évaluer soigneusement s'ils en ont même besoin. Plus tard, ils se sont plaints du fait que Flux était complexe et verbeux, alors qu'en réalité, dans de nombreux cas, ils ont eux-mêmes copié les parties verbeuses (mais non essentielles).

Dans ces cours, je n'enseigne que les parties essentielles de Redux. Remarquez que je n'introduis pas de constantes, parce que les gens se concentrent trop sur elles et s'aperçoivent qu'elles n'ont pas vraiment d'importance. Vous êtes plus susceptible de comprendre les avantages des constantes après avoir fait quelques fautes de frappe dans les chaînes, plutôt que si je les ai mises dans les vidéos du didacticiel dès le début. Je pense qu'il en va de même pour d'autres conventions comme la FSA – par tous les moyens, utilisez-la si vous le trouvez pratique, mais je ne le prêcherai pas si les leçons ne l'exigent pas.

@gaearon OK, je suis avec vous alors, dans l'espoir que ceux qui se sont habitués à la simple approche non structurée ne rendront pas les applications plus volumineuses ingérables en n'appliquant aucune convention.

@sompylasar

Je pense que les exemples affichent les conventions mieux que les didacticiels vidéo. Les exemples sont le pays opiniâtre de « voici comment je vais structurer un code autour de ces principes », et les vidéos traitent de ces principes eux-mêmes. C'est pourquoi vous verrez différentes conventions dans différents exemples, et avant de commencer un projet, la plupart des gens examinent différents exemples pour avoir un avant-goût des différentes manières de le faire.

De plus, il n'y a absolument rien de non structuré à ne pas suivre FSA. { type: 'STUFF', id: 1 } n'est pas intrinsèquement pire que { type: 'STUFF', payload: { id: 1 } } . C'est juste une question de goût et (parfois) de convention d'outillage. Garder les objets d'action en moins de payload ne les rend pas plus difficiles à utiliser.

Nous avons une poignée de leçons de tests unitaires redux qui sortiront bientôt sur egghead 😄

Nous avons suspendu TOUTES les leçons Redux pendant un certain temps afin que Dan ait le premier crack. Cela vaut vraiment la peine d'attendre, et puis certains.

"Créer une application avec Idiomatic Redux" serait un merveilleux cours avancé 👍

@joelhooks, ces deux sons sont incroyables !

J'aimerais vous voir configurer un projet à l'aide de webpack et de rechargement à chaud au lieu d'utiliser jsbin. Prenez ceci dans le monde réel. Je sais que ce n'est pas spécifique au redux mais je pense que ça irait bien et tu es la bonne personne pour enseigner ça :)

@kevinrenskers ce n'est pas une série de vidéos, mais si vous avez envie de disséquer quelque chose, il y a quelques très bons exemples de passe-partout auxquels vous pouvez vous référer !

Ceux qui ont demandé une structure de projet pour l'exemple de Dan et la configuration Webpack.

Veuillez vérifier ceci https://github.com/urbanvikingr/todo.

Je me suis engagé à mettre à jour Redux avec React doc pour qu'il soit aligné avec le code de Dan des vidéos. Ce sera fait dans les deux prochaines semaines - mon projet de vacances :) - restez à l'écoute.

Ma liste de souhaits pour les vidéos Egghead.io :
test d'action / réducteur avec Jasmine
approfondissement sur le middleware (thunk / promesses)

Les screencasts sont une introduction très utile à Redux. Ce que j'aimerais entendre, c'est la méthode Redux pour faire le routage et le rendu côté serveur

@grigio Vous pourriez être intéressé par cette discussion https://github.com/rackt/redux/issues/1145 sur le routage

@urbanvikingr merci, abonné. Le sondage semble clos, mais j'aurais voté #1168

Les leçons sont en fait assez bonnes, mais c'est distrayant que lorsque vous dites « magasin », cela ressemble à une « corvée ».

Tout le monde ici l'a remarqué et a été distrait par cela. Ils sont tout simplement trop politiquement corrects pour en parler. Alors oui, j'ai décidé d'être _ce_ gars, au cas où personne d'autre ne le ferait jamais :)

Je finirai par m'améliorer en anglais. Pour l'instant c'est le mieux que je puisse faire ;-)

@gaearon Vous avez fait un sacré bon travail en expliquant Redux. Bravo à vous et à vos réalisations open source.

Incroyable ensemble de leçons. J'ai particulièrement aimé la façon dont vous avez réimplémenté chacune des fonctions de base de Redux à partir de zéro d'une manière "lire la source". En secondant quelqu'un d'autre qui a été impressionné par la clarté des didacticiels et de toute la documentation pour Redux. Jusqu'à présent, en tant que personne rattrapant deux ans d'avancées frontend, les concepts ont été difficiles à comprendre, mais les documents ont été incroyablement utiles pour le faire. Continuez comme ça et merci !

( N'écoutez pas non plus parler ", ou même se souciait que vous ayez un accent.)

@ianstormtaylor
Ce n'est pas un accent, d'ailleurs :)

Je m'en fichais non plus, mais j'étais certainement distrait !

Mais d'un autre côté, en tant que personne ayant étudié six langues étrangères, j'ai toujours eu à cœur de parler une langue correctement, et à cette fin, j'apprécie personnellement que quelqu'un me signale mes erreurs.

Salut @gaearon ,

J'ai vraiment adoré votre cours. Bon travail! C'était très utile.

J'ai ajouté trois leçons vidéo de test Redux à mon récent cours Egghead :
https://egghead.io/series/react-testing-cookbook

J'espère qu'ils seront complémentaires à tout le travail incroyable que vous avez fait !

Cours solide !

Améliore non seulement les connaissances Redux, mais aussi les connaissances sur les pratiques modernes en général ! Continuez à faire de si bonnes choses :+1: :tada:

hé, je viens de réaliser qu'il n'y a pas de lien/référence au code dans les vidéos. Peut-être évident, et peut-être assez simple, les utilisateurs pourraient simplement copier les vidéos ; mais je pense que beaucoup de gens pourraient bénéficier d'un dépôt avec le code exact dans les vidéos, pourquoi pas ?

Des extraits de code pour chaque leçon sont disponibles pour les abonnés Egghead. :-)
Les vidéos sont gratuites, mais la plateforme doit gagner de l'argent pour pouvoir investir dans plus de cours, envoyer du matériel aux instructeurs, héberger les vidéos, améliorer le site Web, etc.

Cela dit, nous avons un dossier examples/todos qui correspond à peu près au cours.

... cool, ça me manque alors ? Recherche de lien(s)...

@gaearon s'excuse, vient de revoir les vidéos. le code est juste là :)... regardé les vidéos, acheté un abonnement, regardé les autres... je viens de revenir aux vidéos redux réellement connectées. bravo.

Soit dit en passant, quelques personnes se sont plaintes que les transcriptions étaient inexactes.
Veuillez envoyer des PR pour les corriger : https://github.com/eggheadio/egghead-redux-transcripts

@gaearon J'ai décidé d'utiliser redux, puis j'ai trouvé les vidéos redux sur egghead. Les vidéos m'ont vraiment aidé à commencer à apprendre le redux. À l'avenir, ce serait formidable de voir plus d'exemples du monde réel.

Donc, ma suggestion pour la formation vidéo redux à l'avenir serait une composition avancée, une plongée plus profonde dans la refactorisation et certainement comment utiliser la re-sélection. Vous semblez avoir une intuition sur le moment de refactoriser. Ainsi, étant donné que la programmation fonctionnelle est si intimement liée au redux, il serait vraiment utile d'obtenir des conseils de votre part sur le moment de refactoriser et sur la façon d'identifier une fonction qui fait bien une chose.

Dans l'application que je construis, j'ai plusieurs grandes collections de données et je dois les mettre dans des tableaux et faire des choses comme trier et paginer les données. J'ai du mal à décider quand utiliser des sélecteurs et quand utiliser des actions de création. Actuellement, j'ai l'action USERS_SORT_TABLE et l'action SORT_TABLE parce que les utilisateurs stockent "héritant" d'un état de la table. Je l'ai fait parce que je ne voulais pas qu'une action SORT_TABLE sur un magasin de tâches soit triée par le magasin d'utilisateurs.

Je sais que ma solution n'est pas SÈCHE, mais je ne sais pas comment le faire correctement. Dans l'état actuel des choses, je vais devoir créer une action "SOMETHING"_SORT_TABLE pour chaque magasin dans lequel je souhaite remplir une table, ce qui, je le sais, est faux, mais je ne connais pas le bon chemin. Un autre effet secondaire est que le nom de mon action devient énorme car je dois séparer différents magasins en préfixant leur nom à l'action. Cela ne peut pas être juste.

Voici un exemple de code :

/* actions.js */
// ...
export const USER_MOVE_COLUMN = 'USER_MOVE_COLUMN'

export function userMoveColumn (columnIndex, moveToIndex) {
  return {
    type: USER_MOVE_COLUMN,
    columnIndex,
    moveToIndex
  }
}

export const DATA_TABLE_MOVE_COLUMN = 'DATA_TABLE_MOVE_COLUMN'
// ...

/* reducers.js */
// ...
export default function user (state=userInitialState, action) {
  switch (action.type) {
    // ...
    case USER_MOVE_COLUMN:
      return dataTable(state, assign(
        action,
        {type: DATA_TABLE_MOVE_COLUMN}
      ))
    // ...
    default:
      return state
  }
}
// ...
export default function dataTable (
  state=dataTableInitialState,
  action,
  key='dataTable')
{
  switch (action.type) {
    // ...
    case DATA_TABLE_MOVE_COLUMN:
      return {
        ...state,
        [key]: {
          ...state[key],
          columns: move(
            state[key].columns, action.columnIndex, action.moveToIndex
          )
        }
      }
    // ...
    default:
      return state
  }
}

Vous pouvez donc voir que j'ai créé une dépendance entre la table et le magasin "modèle" que je n'aurais pas dû avoir (le magasin de modèles doit utiliser la clé de collection pour son tableau d'objets). Et le dataTable manipule l'état du réducteur "parent", ce qu'il ne devrait pas faire. Il m'est venu à l'esprit que je devais utiliser un sélecteur là-bas, mais au moment où j'ai écrit ceci, j'essayais d'éviter de dupliquer un grand magasin juste pour changer ce qui était visible dans l'interface utilisateur.

Donc, actuellement, j'ai du mal à apprendre à resélectionner pour résoudre certains de ces problèmes et des techniques de refactorisation pour résoudre certains des autres. Le premier cours Redux a suffi à me rendre dangereux. Maintenant, j'aimerais apprendre comment le faire correctement. :)

J'espère que cela a été utile et pas trop verbeux. Essayer de donner des commentaires clairs et honnêtes.

Pour toute âme charitable qui pourrait m'aider, j'ai déjà trouvé /examples/real-world/reducers dans un autre commentaire de Dan et je suis en train de retravailler certains des problèmes que j'ai décrits ci-dessus. Je ne voulais pas que tu perdes du temps à essayer d'aider si j'avais trouvé une solution.

Merci pour l'avertissement :)

intégrer les redux-devtools dans mon projet a été une énorme douleur pour moi .. j'aurais (et j'apprécierai toujours) une série egghead qui décrit ce qui existe et comment / quand l'utiliser. J'ai lu le PR où vous décrivez quand utiliser quoi.

Pour toute autre personne aux prises avec certains des problèmes que j'ai décrits ci-dessus, j'ai créé un projet qui vous permet de supprimer la plupart, sinon la totalité, du passe-partout dans Redux ainsi que les actions d'espace de noms. Voir ça ici

@granteagon n'est-ce pas coupler des réducteurs aux créateurs d'action ? L'un des principes de conception de base de Redux est que les _réducteurs doivent être découplés des actions_. N'importe quel réducteur peut écouter n'importe quelle action. Il n'y a pas de mappage 1:1 entre eux. Sinon, il est difficile pour différentes parties de l'arborescence d'état de modifier indépendamment leur état en réponse aux mêmes actions.

J'ai remarqué que la plupart des gens qui créent des wrappers ou des abstractions en plus de la création d'action/réducteur ont tendance à supposer qu'ils seront toujours directement couplés ensemble. Certes, dans mon application, jusqu'à présent, la plupart de mes actions ont exactement un bloc correspondant de logique de gestion, mais il y en a certainement eu plusieurs où plusieurs parties de l'arbre doivent être mises à jour.

@gaearon @markerikson Il

@granteagon @gaearon

Ayant utilisé une abstraction locale similaire à reduxr, je dirais qu'il n'y a pas de couplage supplémentaire ici. Rien ne force le mappage 1:1 entre les actions et les réducteurs. Vous pouvez toujours avoir deux réducteurs dans deux tranches différentes écoutant la même action :

const counterReducersA = {
  // this counter increments by 1 each time
  increment: (state, action) => state + 1
}

const counterReducersB = {
  // this counter increments by 2 each time
  increment: (state, action) => state + 2
}

const counterA = reduxr(counterReducersA, 0);
const counterB = reduxr(counterReducersB, 0);

const rootReducer = combineReducers({
  counterA: counterA.reducer,
  counterB: counterB.reducer
});

store.dispatch(counterA.action.increment());  // increments both counters

Bien sûr, si vous avez plus d'une fonction "réductrice" nommée pour la même chose (c'est-à-dire répondant à la même action), implicitement, elles doivent toutes les deux "s'attendre" à ce que la charge utile de l'action ait une certaine forme --- ce qui est complètement analogue d'avoir deux réducteurs dans vanilla redux tous les deux gérant la même constante type --- les deux doivent s'attendre à la même forme d'action.

J'ai peut-être mal compris ce que tu entends par couplage, @gaearon ?

Je pense que montrer un flux asynchrone sans middleware avant de montrer la mise en œuvre du thunk pourrait être utile.

Un peu lié, mais bien que la documentation ait été incroyablement utile, cette déclaration sur la page des flux asynchrones m'a vraiment fait dérailler avec le recul : « Sans middleware, le magasin Redux ne prend en charge que les flux de données synchrones. »

@battaile : c'est parce que c'est vrai :) Sans middleware, toute asynchronisme doit se produire complètement en dehors de Redux (donc, très probablement dans votre couche d'interface utilisateur, comme les composants React). Chaque fois que vous appelez store.dispatch , l'action ira directement à la fonction de

Les amplificateurs de magasin vous permettent d'encapsuler des fonctions telles que dispatch avec votre propre version, et ainsi applyMiddleware fournit l'abstraction d'un "pipeline middleware" avant que quelque chose n'atteigne la fonction dispatch du magasin réel . Cela fournit essentiellement une échappatoire où vous pouvez sauter et faire tout ce que vous voulez, à l'intérieur du flux Redux standard.

Ainsi, sans middleware, vous pouvez toujours faire des choses totalement asynchrones...

c'est parce que c'est vrai :)

Je n'ai pas dit que c'était faux, j'ai dit que ça m'avait fait dérailler :)

Je voulais juste faire quelque chose comme ce qui suit, ce qui semblait impliquer que je ne pouvais pas :

const mapDispatchToProps = (dispatch) => ({
  onclick(searchTerm) {
    dispatch(actions.requestOrders(searchTerm));

    return fetch('http://localhost:49984/Order/Search?search=' + searchTerm)
      .then(response => response.json()).then(response => {
        dispatch(actions.receiveOrders(searchTerm, response));
      })
      .catch((err) => {
        dispatch(actions.receiveOrdersError('An error occurred during search: ' + err.message));
      });
  },
});

Je me rends compte que cela pourrait facilement devenir moche, mais conceptuellement, je pense que c'est utile à voir. Ou du moins c'était dans mon cas.

Je suis d'accord que "Sans middleware, le magasin Redux ne prend en charge que le flux de données synchrone." est trompeur.

Techniquement, si vous voulez faire une distinction entre "à l'intérieur" et "à l'extérieur", la déclaration peut être vraie, mais si cela amène les gens à croire que la seule façon de faire async est d'ajouter un middleware, peut-être pouvons-nous la reformuler ou élaborer sur ce.

Oui, la différence est que le comportement asynchrone se produit techniquement davantage au niveau du composant, plutôt qu'à "l'intérieur" de dispatch . Une distinction mineure, mais valable.

Je ne pense pas que quiconque prétende que la déclaration n'est pas techniquement correcte.

@markerikson Juste curieux de savoir si vous avez des exemples concrets où la distinction entre l'intérieur et l'extérieur compte ?

Un exemple pourrait être si vous voulez un middleware dans la chaîne _avant_ votre middleware asynchrone pour pouvoir voir votre thunk (ou promesse, etc.) expédié. Je ne suis pas sûr de ce que ce middleware ferait, mais je suppose qu'il est possible de vouloir une telle chose.

Mmm... pas sûr des exemples "concrets" en particulier. Dans l'ensemble, la distinction entre « dehors » et « insie » est de savoir si cela se produit _avant_ d'appeler dispatch la première fois, ou _après_. Si c'est "à l'extérieur" et "avant", alors toute votre asynchronisme et votre logique sont davantage liées à la couche de vue, qu'il s'agisse de React, Angular ou autre. Si c'est "à l'intérieur" et "après", alors votre asynchronisme et votre logique sont au niveau du magasin et _pas_ liées à la couche de vue.

C'est en fait une grande partie du point que j'essayais de faire valoir dans une discussion sur Reddit plus tôt dans la journée : https://www.reddit.com/r/reactjs/comments/4spbip/has_anyone_inserted_a_controllerpresenter_layer/ .

La question de "quelles actions dois-je envoyer et quand est-ce que je les envoie ?" est un élément central de votre logique métier, l'autre moitié étant "comment mettre à jour mon état en réponse à ces actions ?". Si la gestion des actions est dans les thunks et les sagas et autres, peu importe que ce code ait été lancé par un composant React, un contrôleur angulaire, un gestionnaire de clics jQuery, une instance de composant Vue ou autre chose. Votre logique de base est en dehors de la couche d'interface utilisateur, et la couche d'interface utilisateur est en réalité uniquement chargée d'extraire les données dont elle a besoin du magasin, de les afficher et de transformer les entrées de l'utilisateur en un appel de fonction logique d'application.

Donc, dans ce sens, je dirais que la question "à l'intérieur" contre "à l'extérieur" est importante, car c'est une distinction conceptuelle entre si votre logique vit au niveau de l'application ou au niveau de l'interface utilisateur.

@markerikson merci d'avoir

Remarque : pour plus de commodité, je vais utiliser thunk pour représenter une approche middleware abritée de l'async, qu'il s'agisse en fait de redux-thunk ou de redux-promise, ou autre.

Votre couche d'interface utilisateur ne fait que connecter les interactions des utilisateurs aux gestionnaires. Lorsque quelqu'un clique sur un bouton, votre interface utilisateur est configurée pour appeler _some_ handler. Souvent, le composant reçoit ces gestionnaires en tant qu'accessoires --- peut-être un créateur d'action lié, par exemple. L'interface utilisateur ne sait pas ce qui se passe lorsqu'elle appelle un gestionnaire --- elle l'appelle simplement.

Cela ne fait aucune différence pour la couche d'interface utilisateur que le "gestionnaire" envoie une fonction (à gérer par un middleware) ou s'il exécute un appel asynchrone et _then_ envoie une action simple --- l'interface utilisateur est complètement agnostique (ou du moins, elle _peut_ être agnostique)

Une grande partie de votre "application" se trouve dans ces "gestionnaires", que vous utilisiez des thunks ou non. Dans une application de réaction/redux typique, ces "gestionnaires" sont souvent des créateurs d'action. Vous pouvez écrire tous vos trucs asynchrones sous forme de thunks et les envoyer. Ou, vous pouvez écrire tous vos trucs asynchrones sous forme de fonctions qui acceptent dispatch comme argument. Du point de vue du composant, c'est soit someHandler(dispatch) OU dispatch(someHandler()) , ou dans le cas des créateurs d'action liés transmis de plus haut, c'est juste someHandler() dans les deux cas. Vous pouvez créer une version de bindActionCreators qui masquerait complètement cette différence par rapport à la couche d'interface utilisateur.

Si vous me donnez une application de réaction/redux écrite avec des créateurs d'action utilisant redux-thunk, je pourrais complètement remplacer redux-thunk et utiliser une approche non middleware sans changer _fondamentalement_ la couche d'interface utilisateur. (remarque : je ne précise pas où/comment vous injectez getState , mais je pense que c'est un détail mineur ici).

Par conséquent, j'ai du mal à accepter que la distinction entre "intérieur" et "extérieur" soit "niveau application" ou "niveau UI".

J'apprécie la discussion, et j'espère que je n'ai pas l'air négatif.

Ce cours est super. Clôturer ceci afin que les gens puissent adresser leurs commentaires au référentiel de notes de la communauté pour le cours : https://github.com/tayiorbeii/egghead.io_redux_course_notes

N'oubliez pas non plus de jeter un œil à la prochaine série que Dan a mise en place ! https://egghead.io/courses/building-react-applications-with-idiomatic-redux

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

Questions connexes

ms88privat picture ms88privat  ·  3Commentaires

vraa picture vraa  ·  3Commentaires

caojinli picture caojinli  ·  3Commentaires

timdorr picture timdorr  ·  3Commentaires

jimbolla picture jimbolla  ·  3Commentaires