Componente React inicializar estado desde props


En React, ¿hay alguna diferencia real entre estas dos implementaciones? Algunos amigos me dicen que el primer componente es el patrón, pero no veo por qué. El SecondComponent parece más simple porque el render se llama solo una vez.

Primero:

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;

Segundo:

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;

Actualizar: Cambié setState () a esto.state = {} (gracias joews), Sin embargo, todavía no veo la diferencia. ¿Es uno mejor que el otro?

Author: Jason, 2016-10-15

5 answers

Debe tenerse en cuenta que es un anti-patrón para copiar propiedades que nunca cambian al estado (solo access .atrezzo directamente en ese caso). Si tiene una variable de estado que cambiará eventualmente pero comienza con un valor de.props, ni siquiera necesitas una llamada al constructor-estas variables locales se inicializan después de una llamada al constructor del padre:

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

Esta es una abreviatura equivalente a la respuesta de @joews a continuación. Parece que solo funciona en versiones más recientes de es6 transpilers, he tenido problemas con él en algunas configuraciones webpack. Si esto no funciona para usted, la versión no abreviada de @joews lo hará.

 47
Author: Zane Hooper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-23 18:53:53

No es necesario llamar a setState en un Componente constructor - es idiomático establecer this.state directamente:

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

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

Ver React docs - Añadir Estado Local a una Clase.

No hay ninguna ventaja para el primer método que usted describe. Dará lugar a una segunda actualización inmediatamente antes de montar el componente por primera vez.

 93
Author: joews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 12:29:36

Introducción de la actualización para React 16.3 alphastatic getDerivedStateFromProps(nextProps, prevState) (docs ) en sustitución de componentWillReceiveProps.

GetDerivedStateFromProps se invoca después de que se instancie un componente, así como cuando recibe nuevos props. Debe devolver un objeto para actualizar el estado, o null para indicar que las nuevas props no requieren ninguna actualización de estado.

Tenga en cuenta que si un componente padre hace que su componente vuelva a renderizarse, se llamará a este método incluso si las props no han cambiado. Es posible que desee comparar valores nuevos y anteriores si solo desea manejar los cambios.

Es estático, por lo tanto no tiene acceso directo a this (sin embargo, sí tiene acceso a prevState, que podría almacenar cosas que normalmente se adjuntan a this, por ejemplo, refs)

editado para reflejar la corrección de @ nerfologist en comentarios

 12
Author: Ashley Coolman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-15 15:28:30

Puede usar el formulario corto como el siguiente si desea agregar todos los accesorios al estado y conservar los mismos nombres.

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}
 9
Author: dacharjaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-28 08:17:10

Si inicias directamente el estado desde props, se mostrará una advertencia en React 16.5 (5 de septiembre de 2018)

 0
Author: sujithklr93,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-10 03:53:40