¿Puedo actualizar los accesorios de un componente en React.js?

217

Después de comenzar a trabajar con React.js, parece que propsestán destinados a ser estáticos (pasados ​​desde el componente principal), mientras que los statecambios se basan en eventos. Sin embargo, noté en los documentos una referencia acomponentWillReceiveProps , que incluye específicamente este ejemplo:

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

Esto parece implicar que las propiedades PUEDEN cambiar en un componente basado en la comparación de nextPropsto this.props. ¿Qué me estoy perdiendo? ¿Cómo cambian los accesorios, o me equivoco acerca de dónde se llama esto?

Matt Huggins
fuente

Respuestas:

249

Un componente no puede actualizar sus propios accesorios a menos que sean matrices u objetos (que un componente actualice sus propios accesorios incluso si es posible es un antipatrón), pero puede actualizar su estado y los accesorios de sus hijos.

Por ejemplo, un Tablero tiene un speedcampo en su estado y se lo pasa a un hijo de Indicador que muestra esta velocidad. Su rendermétodo es justo return <Gauge speed={this.state.speed} />. Cuando el Tablero llama this.setState({speed: this.state.speed + 1}), el Indicador se vuelve a representar con el nuevo valor para speed.

Justo antes de que esto suceda, componentWillReceivePropsse llama Gauge's , para que Gauge tenga la oportunidad de comparar el nuevo valor con el anterior.

Valéry
fuente
Por lo tanto, parece que se llama una vez cuando el componente React se inicializa y recibe accesorios. Los accesorios en realidad no "cambian" una vez que se crea un componente. ¿Está bien?
Matt Huggins
12
Lo contrario. La documentación dice: "Se invoca cuando un componente recibe nuevos accesorios. Este método no se llama para el renderizado inicial".
Valéry
Gracias. Esta pregunta vino de un malentendido inicial de React en que un componente se reutilizará al volver a mostrar la pantalla (o parte de la pantalla).
Matt Huggins
1
Si. Un componente puede escuchar un evento y actualizar su estado cada vez que se dispara el evento.
Valéry
8
Vengo del futuro: componentWillReceivePropsestá desactualizado ahora: y reemplazado por una combinación de getDerivedStateFromPropsy componentDidUpdate.
bvdb
53

ACCESORIOS

Un componente React debe usar accesorios para almacenar información que se puede cambiar, pero que solo puede cambiar un componente diferente.

ESTADO

Un componente React debe usar el estado para almacenar información que el componente en sí mismo puede cambiar.

Valéry ya proporciona un buen ejemplo.

Ali Adravi
fuente
44
@ali_adravi ¿se copian esas citas de alguna parte? Si es así, ¿cuál es la referencia? ¿O son esas sus palabras y las ha formateado como citas para enfatizar?
Rob Bednark
@RobBednark No recuerdo la fuente exacta ahora, pero seguro que es una declaración verdadera con una pequeña modificación en la oración de algún libro.
Ali Adravi
26

Los accesorios pueden cambiar cuando el padre de un componente vuelve a representar el componente con diferentes propiedades. Creo que esto es principalmente una optimización para que no se necesite instanciar ningún componente nuevo.

Joost Diepenmaat
fuente
3

Truco para actualizar accesorios si son array:

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
fuente
3
Estoy pensando que inicializar el estado con accesorios es antipatrón, debería evitarse. Aquí está el buen enlace para leer github.com/vasanthk/react-bits/blob/master/anti-patterns/… .
tryHendri
0

si usa recompose, use mapPropspara hacer nuevos accesorios derivados de accesorios entrantes

Editar por ejemplo:

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
fuente
proporcione un ejemplo
vsync