Puis-je mettre à jour les accessoires d'un composant dans React.js?

217

Après avoir commencé à travailler avec React.js, il semble qu'ils propssoient destinés à être statiques (transmis depuis le composant parent), tandis que les statechangements sont basés sur les événements. Cependant, j'ai remarqué dans les documents une référence à componentWillReceiveProps, qui inclut spécifiquement cet exemple:

componentWillReceiveProps: function(nextProps) {
  this.setState({
    likesIncreasing: nextProps.likeCount > this.props.likeCount
  });
}

Cela semble impliquer que les propriétés PEUVENT changer sur un composant basé sur la comparaison de nextPropsà this.props. Qu'est-ce que je rate? Comment les accessoires changent-ils ou me trompe-t-on sur la façon dont cela s'appelle?

Matt Huggins
la source

Réponses:

250

Un composant ne peut pas mettre à jour ses propres accessoires à moins qu'il ne s'agisse de tableaux ou d'objets (le fait qu'un composant mette à jour ses propres accessoires, même si c'est possible est un anti-modèle), mais peut mettre à jour son état et les accessoires de ses enfants.

Par exemple, un tableau de bord a un speedchamp dans son état et le transmet à un enfant Gauge qui affiche cette vitesse. Sa renderméthode est juste return <Gauge speed={this.state.speed} />. Lorsque le tableau de bord appelle this.setState({speed: this.state.speed + 1}), la jauge est restituée avec la nouvelle valeur de speed.

Juste avant que cela ne se produise, la jauge componentWillReceivePropsest appelée, afin que la jauge ait une chance de comparer la nouvelle valeur à l'ancienne.

Valéry
la source
Il semble donc qu'il soit appelé une fois lorsque le composant React est initialisé et reçoit des accessoires. Les accessoires ne "changent" pas réellement une fois qu'un composant est créé. Est-ce correct?
Matt Huggins
12
L'opposé. La documentation indique: "Appelé lorsqu'un composant reçoit de nouveaux accessoires. Cette méthode n'est pas appelée pour le rendu initial."
Valéry
Merci. Cette question provient d'une mauvaise compréhension initiale de React en ce sens qu'un composant sera réutilisé lors du rendu de l'écran (ou d'une partie de l'écran).
Matt Huggins
1
Oui. Un composant peut écouter un événement et mettre à jour son état à chaque déclenchement de l'événement.
Valéry
8
Je viens du futur: componentWillReceivePropsest dépassé maintenant: et remplacé par une combinaison de getDerivedStateFromPropset componentDidUpdate.
bvdb
53

PROPS

Un composant React doit utiliser des accessoires pour stocker des informations qui peuvent être modifiées, mais ne peuvent être modifiées que par un autre composant.

ETAT

Un composant React doit utiliser l'état pour stocker des informations que le composant lui-même peut modifier.

Un bon exemple est déjà fourni par Valéry.

Ali Adravi
la source
4
@ali_adravi ces citations sont-elles copiées quelque part? Si oui, quelle est la référence? Ou est-ce que ce sont vos mots, et vous les avez simplement mis en forme comme des guillemets à souligner?
Rob Bednark
@RobBednark Je ne me souviens pas de la source exacte maintenant, mais bien sûr, c'est une affirmation vraie avec une petite modification dans la phrase d'un livre.
Ali Adravi
26

Les accessoires peuvent changer lorsque le parent d'un composant rend à nouveau le composant avec des propriétés différentes. Je pense que c'est surtout une optimisation afin qu'aucun nouveau composant ne doive être instancié.

Joost Diepenmaat
la source
3

Astuce pour mettre à jour les accessoires s'ils sont des tableaux:

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Button
} from 'react-native';

class Counter extends Component {
  constructor(props) {
    super(props);
      this.state = {
        count: this.props.count
      }
    }
  increment(){
    console.log("this.props.count");
    console.log(this.props.count);
    let count = this.state.count
    count.push("new element");
    this.setState({ count: count})
  }
  render() {

    return (
      <View style={styles.container}>
        <Text>{ this.state.count.length }</Text>
        <Button
          onPress={this.increment.bind(this)}
          title={ "Increase" }
        />
      </View>
    );
  }
}

Counter.defaultProps = {
 count: []
}

export default Counter
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});
Abhishek Kumar
la source
3
Je pense que l'initialisation de l'état avec des accessoires est anti-modèle, devrait être évitée. voici le bon lien pour lire github.com/vasanthk/react-bits/blob/master/anti-patterns/… .
tryHendri
0

si vous utilisez recompose, utilisez mapPropspour créer de nouveaux accessoires dérivés des accessoires entrants

Modifiez par exemple:

import { compose, mapProps } from 'recompose';

const SomeComponent = ({ url, onComplete }) => (
  {url ? (
    <View />
  ) : null}
)

export default compose(
  mapProps(({ url, storeUrl, history, ...props }) => ({
    ...props,
    onClose: () => {
      history.goBack();
    },
    url: url || storeUrl,
  })),
)(SomeComponent);
ehacinom
la source
veuillez fournir un exemple
vsync