287 votes

React : pourquoi le composant enfant n'est pas mis à jour lorsque la prop change ?

Pourquoi, dans l'exemple de pseudo-code suivant, l'enfant ne se présente pas à nouveau lorsque le conteneur change foo.bar ?

Container {
  handleEvent() {
    this.props.foo.bar = 123
  },

  render() {
    return <Child bar={this.props.foo.bar} />
}

Child {
  render() {
    return <div>{this.props.bar}</div>
  }
}

Même si j'appelle forceUpdate() après avoir modifié la valeur dans Container, Child affiche toujours l'ancienne valeur.

13 votes

C'est votre code ? Il semble que ce ne soit pas un code React valide.

0 votes

Je pense que la valeur des props ne devrait pas changer dans le composant du conteneur mais plutôt dans le composant parent par setState et cet état devrait être mappé aux props du conteneur.

0 votes

Utilisez l'opérateur d'étalement comme ceci <Child bar={...this.props.foo.bar} />

341voto

PolinaC Points 354

Mettez à jour l'enfant pour que l'attribut "key" soit égal au nom. Le composant sera rendu à nouveau chaque fois que la clé sera modifiée.

Child {
  render() {
    return <div key={this.props.bar}>{this.props.bar}</div>
  }
}

16 votes

Merci pour cela. J'utilisais redux store et je ne pouvais pas faire en sorte que mon composant soit rendu à nouveau jusqu'à ce que j'ajoute une clé. (J'ai utilisé la bibliothèque uuid pour générer une clé aléatoire, et ça a marché).

0 votes

En utilisant les hooks, mon enfant ne se rendait pas à nouveau lorsqu'il définissait l'état d'un tableau existant. Mon astuce (probablement une mauvaise idée) consistait à définir simultanément l'état d'un accessoire fictif et à l'ajouter au tableau de dépendances useEffect : [props.notRenderingArr, props.dummy] . Si la longueur du tableau change toujours, vous pouvez définir le tableau de dépendance useEffect comme suit [props.notRenderingArr.length] .

13 votes

C'est ce dont j'avais besoin aussi. Je suis perplexe, quand est-ce qu'un key nécessaire, par rapport à juste setState ? J'ai quelques enfants qui dépendent de l'état des parents, mais ils ne déclenchent pas un re-rendu...

147voto

François Richard Points 3542

Parce que les enfants ne sont pas rerendus si les props du parent changent, mais si son STATE change :)

Ce que vous montrez est ceci : https://facebook.github.io/react/tips/communicate-between-components.html

Il transmet les données du parent à l'enfant par le biais de props, mais il n'y a pas de logique de rendu.

Vous devez définir un certain état pour le parent, puis rendre à nouveau l'enfant lorsque le parent change d'état. Ceci pourrait vous aider. https://facebook.github.io/react/tips/expose-component-functions.html

7 votes

Pourquoi setState provoque-t-il un nouveau rendu, mais pas forceUpdate ? Aussi un peu hors sujet, mais comment les composants sont mis à jour quand les props sont passés de redux et que l'état est mis à jour par l'action ?

1 votes

Les props ne sont pas mis à jour même si vous mettez à jour le composant, les props que vous avez passés sont toujours là. Flux est un autre sujet oui :)

4 votes

State != props, vous devez en savoir plus à ce sujet. Vous ne faites pas de mises à jour avec les props

13voto

Sujan Thakare Points 590

Selon la philosophie React, un composant ne peut pas changer ses props. Ils doivent être reçus du parent et doivent être immuables. Seul le parent peut modifier les props de ses enfants.

bonne explication sur État et accessoires

également, lisez ce fil de discussion Pourquoi je ne peux pas mettre à jour les props dans react.js ?

0 votes

Cela ne signifie-t-il pas également que le conteneur ne peut pas modifier les props qu'il reçoit du magasin redux ?

4 votes

Le conteneur ne reçoit pas les props directement du magasin, ils sont fournis par la lecture d'une partie de l'arbre d'état redux (déroutant ??)! ! la confusion est due au fait que nous ne connaissons pas la fonction magique connect de react-redux. si vous regardez le code source de la méthode connect, elle crée un composant d'ordre supérieur qui a un état avec la propriété storeState et qui est abonné au magasin redux. lorsque le storeState change, tout le re-rendu se produit, et les props modifiés sont fournis au conteneur par la lecture de l'état modifié. j'espère que cela répond à la question

0 votes

Bonne explication, la réflexion sur la composante d'ordre supérieur m'aide à comprendre ce qui se passe.

8voto

JamesYin Points 161

Vous devez utiliser setState fonction. Si ce n'est pas le cas, l'État n'enregistrera pas votre modification, quelle que soit la façon dont vous utilisez forceUpdate.

Container {
    handleEvent= () => { // use arrow function
        //this.props.foo.bar = 123
        //You should use setState to set value like this:
        this.setState({foo: {bar: 123}});
    };

    render() {
        return <Child bar={this.state.foo.bar} />
    }
    Child {
        render() {
            return <div>{this.props.bar}</div>
        }
    }
}

Votre code ne semble pas valide. Je ne peux pas tester ce code.

0 votes

Cela ne devrait-il pas être <Child bar={this.state.foo.bar} /> ?

0 votes

Bien. Je mets à jour la réponse. Mais comme je l'ai dit, ce n'est peut-être pas un code valide. Il suffit de copier la question.

1voto

Indraneel Bende Points 39

Utilisez la fonction setState. Vous pourriez donc faire

       this.setState({this.state.foo.bar:123}) 

dans la méthode de gestion de l'événement.

Une fois que l'état est mis à jour, cela déclenchera des changements, et un nouveau rendu aura lieu.

2 votes

Ça devrait être this.setState({foo.bar:123}), non ?

1 votes

Ce n'est même pas en train d'être compilé. Je pense que vous vouliez dire : this.setState({ foo : { bar : 123 } })

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X