web-dev-qa-db-fra.com

React le composant initialise l'état à partir des accessoires

Dans React, existe-t-il de réelles différences entre ces deux implémentations? Certains amis me disent que le premier composant est le motif, mais je ne vois pas pourquoi. Le SecondComponent semble plus simple car le rendu n'est appelé qu'une seule fois.

Première:

import React, { PropTypes } from 'react'

class FirstComponent extends React.Component {

  state = {
    description: ''
  }

  componentDidMount() {
    const { description} = this.props;
    this.setState({ description });
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} /> 
    );
  }
}

export default FirstComponent;

Seconde:

import React, { PropTypes } from 'react'

class SecondComponent extends React.Component {

  state = {
    description: ''
  }

  constructor (props) => {
    const { description } = props;
    this.state = {description};
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} />   
    );
  }
}

export default SecondComponent;

Mise à jour: j'ai changé setState () en this.state = {} (merci joews). Cependant, je ne vois toujours pas la différence. Est-ce que l'un est meilleur qu'un autre?

153
Levy Moreira

Il convient de noter que copier des propriétés qui ne changent jamais d’état est un anti-modèle (il suffit d’accéder directement à .props dans ce cas). Si vous avez une variable d'état qui va éventuellement changer, mais qui commence par une valeur provenant de .props, vous n'avez même pas besoin d'un appel de constructeur. Ces variables locales sont initialisées après un appel au constructeur du parent:

class FirstComponent extends React.Component {
  state = {
    x: this.props.initialX,
    // You can even call functions and class methods:
    y: this.someMethod(this.props.initialY),
  };
}

Ceci est un raccourci équivalent à la réponse de @joews ci-dessous. Il semble que cela ne fonctionne que sur les versions les plus récentes d'es6 transpilers. J'ai eu des problèmes avec cela sur certaines configurations de webpack. Si cela ne fonctionne pas pour vous, vous pouvez essayer d'ajouter le plugin babel babel-plugin-transform-class-properties, ou vous pouvez utiliser la version non abrégée de @joews ci-dessous.

154
Zane Hooper

Il n'est pas nécessaire d'appeler setState dans le nom d'un composant constructor - il est idiomatique de définir this.state directement:

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      x: props.initialX
    };
  }
  // ...
}

Voir Documents de réaction - Ajout d'un état local à une classe .

La première méthode que vous décrivez ne présente aucun avantage. Cela entraînera une deuxième mise à jour immédiatement avant de monter le composant pour la première fois.

121
joews

Mise à jour pour React 16.3 alpha introduit static getDerivedStateFromProps(nextProps, prevState) ( docs ) en remplacement de componentWillReceiveProps.

getDerivedStateFromProps est invoqué après l'instanciation d'un composant, ainsi que lorsqu'il reçoit de nouveaux accessoires. Il doit renvoyer un objet pour mettre à jour l'état ou null pour indiquer que les nouvelles propriétés ne nécessitent aucune mise à jour d'état.

Notez que si un composant parent entraîne le rendu de votre composant, cette méthode sera appelée même si les accessoires n'ont pas changé. Vous souhaiterez peut-être comparer les valeurs nouvelles et précédentes si vous souhaitez uniquement gérer les modifications.

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

C'est statique, donc il n'a pas d'accès direct à this (cependant, il a accès à prevState, ce qui pourrait stocker des éléments normalement attachés à this par exemple refs)

modifié pour refléter la correction de @ nerfologist dans les commentaires

31
Ashley Coolman

Vous pouvez utiliser la forme abrégée décrite ci-dessous si vous souhaitez ajouter tous les accessoires pour indiquer et conserver les mêmes noms.

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}
13
dacharjaya

Si vous initiez directement l'état depuis les accessoires, un avertissement apparaîtra dans React 16.5 (5 septembre 2018)

3
sujithklr93

vous pouvez utiliser la valeur key pour réinitialiser l’état en cas de besoin, puis transmettez aux accessoires le fait que ce n’est pas une bonne pratique, car vous avez un composant non contrôlé et contrôlé à un seul endroit. Les données doivent être stockées dans un endroit unique, comme suit: composant non contrôlé avec une clé

2

définir les données d'état à l'intérieur du constructeur comme celui-ci

constructor(props) {
    super(props);
    this.state = {
      productdatail: this.props.productdetailProps
    };
  }

il ne fonctionnera pas si vous définissez la méthode sideDeMount () à l'aide d'accessoires.

0