web-dev-qa-db-fra.com

Comment un composant connecté par redux sait-il quand re-rendre?

Il me manque probablement quelque chose de très évident et j'aimerais me dégager. 

Voici ma compréhension.
Dans une composante de réaction naïve, nous avons states & props. La mise à jour de state avec setState rend à nouveau le composant entier. props sont la plupart du temps en lecture seule et leur mise à jour n’a aucun sens. 

Dans un composant de réaction qui est abonné à un magasin redux, via quelque chose comme store.subscribe(render), il restitue évidemment le rendu à chaque fois que le magasin est mis à jour. 

react-redux a un assistant connect() qui injecte une partie de l’arbre d’état (qui présente un intérêt pour le composant) et actionCreators sous la forme props du composant, généralement via 

const TodoListComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

Cependant, étant entendu que la valeur setState est essentielle pour que TodoListComponent réagisse au changement d'arborescence d'état redux (retransformation), je ne trouve aucun code associé à state ou setState dans le fichier de composant TodoList. Il se lit comme ceci:

const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
        onClick={() => onTodoClick(todo.id)}
      />
    )}
  </ul>
)

Quelqu'un peut-il me diriger dans la bonne direction quant à ce qui me manque?

P.S Je suis l'exemple de liste de tâches fourni avec le paquetage redux ( https://github.com/reactjs/redux/tree/master/examples/todos/src/containers ).

41
Joe Lewis

La fonction connect génère un composant wrapper qui s'abonne au magasin. Lorsqu'une action est distribuée, le rappel du composant encapsuleur est notifié. Il exécute ensuite votre fonction mapState et shallow-compare le résultat obtenu à partir de cette heure contre le résultat précédent (si vous deviez réécrirecela ne déclencherait pas un re-rendu). Si les résultats sont différents, les résultats sont alors transmis à votre "véritable" composant "en tant qu'accessoires.

Dan Abramov a écrit une excellente version simplifiée de connect à https://Gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e qui illustre l’idée de base, bien qu’elle ne montre aucun travail d’optimisation. J'ai également des liens vers un certain nombre d'articles sur Redux performance qui traitent de certaines idées connexes.

mettre à jour

React-Redux v6.0.0 a apporté des modifications internes majeures à la manière dont les composants connectés reçoivent leurs données du magasin.

Dans le cadre de ce travail, j’ai écrit un article qui explique le fonctionnement de l’API connect et de ses internes, ainsi que leur évolution au fil du temps:

Redux idiomatique: historique et implémentation de React-Redux

63
markerikson

Ma réponse est un peu en dehors du champ gauche. Cela met en lumière un problème qui m'a amené à ce poste. Dans mon cas, il me semblait que l'application n'était pas un nouveau rendu, même si elle recevait de nouveaux accessoires.
React devs avait une réponse à cette question souvent posée: si le (magasin) était muté, 99% du temps, c’est la raison pour laquelle réagit ne restitue pas le rendu. 1%. La mutation n'était pas le cas ici.


TLDR;

componentWillReceiveProps indique comment la state peut être synchronisée avec la nouvelle props.

Cas Edge: Une fois state mises à jour, alors l'application fait re-rendre!


Il s'avère que si votre application utilise uniquement state pour afficher ses éléments, props peut se mettre à jour, mais state ne le fera pas, ainsi aucun rendu ne sera rendu.

J'avais state qui dépendait de props reçu de redux store. Les données dont j'avais besoin n'étaient pas encore dans le magasin, alors je les ai extraites de componentDidMount, comme il convient. J'ai récupéré les accessoires lorsque mon réducteur a mis à jour son magasin, car mon composant est connecté via mapStateToProps. Mais la page n'a pas rendu, et l'état était toujours plein de chaînes vides.

Un exemple de ceci est qu'un utilisateur a chargé une page "modifier le message" à partir d'une URL sauvegardée. Vous avez accès à la variable postId à partir de l'URL, mais les informations ne sont pas encore dans la variable store. Vous devez donc les récupérer. Les éléments de votre page sont des composants contrôlés. Ainsi, toutes les données que vous affichez sont dans state.

À l'aide de redux, les données ont été extraites, le magasin a été mis à jour et le composant est connected, mais l'application n'a pas reflété les modifications. À y regarder de plus près, props ont été reçus, mais l'application n'a pas été mise à jour. state n'a pas été mis à jour.

props se mettra à jour et se propagera, mais state ne le fera pas . Vous devez spécifiquement indiquer à state de se mettre à jour. 

Vous ne pouvez pas faire cela dans render(), et componentDidMount est déjà terminé ses cycles.

componentWillReceiveProps est l'endroit où vous mettez à jour les propriétés state qui dépendent d'une valeur prop modifiée.

Exemple d'utilisation:

componentWillReceiveProps(nextProps){
  if (this.props.post.category !== nextProps.post.category){
    this.setState({
      title: nextProps.post.title,
      body: nextProps.post.body,
      category: nextProps.post.category,
    })
  }      
}

Je me dois de citer cet article qui m'a éclairé sur la solution que des dizaines d'autres publications, blogs et pensions n'ont pas mentionné. Toute autre personne qui a eu du mal à trouver une réponse à ce problème évidemment obscur, la voici:

Méthodes du cycle de vie des composants ReactJs - Une plongée profonde

componentWillReceiveProps est l'endroit où vous mettrez à jour state pour rester synchronisé avec les mises à jour props.

Une fois que state est mis à jour, alors champs en fonction de statedo re-rendre!

6
SherylHohman

comme je sais que la seule chose que redux fait, lors du changement d'état du magasin, on appelle composantWillRecieveProps si votre composant dépend de l'état muté et que vous devez obliger votre composant à mettre à jour

1 appel d'état de changement de magasin-2 (composantWillRecieveProps (() => {changement d'état de 3 composants})))

0
ghazaleh javaheri