Posso aggiornare gli oggetti di scena di un componente in React.js?


225

Dopo aver iniziato a lavorare con React.js, sembra che propssiano destinati a essere statici (passati dal componente genitore), mentre i statecambiamenti si basano sugli eventi. Tuttavia, ho notato nei documenti un riferimento a componentWillReceiveProps, che include specificamente questo esempio:

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

Ciò sembra implicare che le proprietà POSSONO cambiare su un componente in base al confronto di nextPropsa this.props. Cosa mi manca? Come cambiano gli oggetti di scena o mi sbaglio su dove viene chiamato?

Risposte:


257

Un componente non può aggiornare i propri oggetti di scena a meno che non siano array o oggetti (avere un componente che aggiorna i propri oggetti di scena anche se possibile è un anti-pattern), ma può aggiornare il suo stato e gli oggetti di scena dei suoi figli.

Ad esempio, un dashboard ha un speedcampo nel suo stato e lo passa a un figlio Gauge che mostra questa velocità. Il suo rendermetodo è giusto return <Gauge speed={this.state.speed} />. Quando il dashboard chiama this.setState({speed: this.state.speed + 1}), il Gauge viene nuovamente renderizzato con il nuovo valore per speed.

Poco prima che ciò accada, componentWillReceivePropsviene chiamato Gauge , in modo che il Gauge abbia la possibilità di confrontare il nuovo valore con quello vecchio.


Quindi sembra che venga chiamato una volta quando il componente React viene inizializzato e riceve oggetti di scena. Gli oggetti di scena in realtà non "cambiano" una volta creato un componente. È giusto?
Matt Huggins

12
L'opposto. La documentazione dice: "Richiamato quando un componente riceve nuovi oggetti di scena. Questo metodo non viene chiamato per il rendering iniziale."
Valéry

Grazie. Questa domanda è nata da un malinteso iniziale di React in quanto un componente verrà riutilizzato quando si esegue nuovamente il rendering dello schermo (o parte dello schermo).
Matt Huggins

1
Sì. Un componente può ascoltare un evento e aggiornarne lo stato ogni volta che l'evento si attiva.
Valéry

9
Vengo dal futuro: componentWillReceivePropsora è obsoleto: e sostituito da una combinazione di getDerivedStateFromPropse componentDidUpdate.
bvdb

59

PUNTELLI

Un componente React dovrebbe usare props per memorizzare informazioni che possono essere modificate, ma possono essere modificate solo da un componente diverso.

STATO

Un componente React dovrebbe usare lo stato per memorizzare le informazioni che il componente stesso può cambiare.

Un buon esempio è già fornito da Valéry.


4
@ali_adravi sono quelle citazioni copiate da qualche parte? In caso affermativo, qual è il riferimento? O quelle sono le tue parole e le hai appena formattate come virgolette per enfatizzare?
Rob Bednark,

@ RobBednark Non ricordo la fonte esatta ora, ma sono sicuro che è un'affermazione vera con una piccola modifica nella frase da qualche libro.
Ali Adravi

26

Gli oggetti di scena possono cambiare quando il genitore di un componente esegue nuovamente il rendering del componente con proprietà diverse. Penso che questa sia principalmente un'ottimizzazione in modo che nessun nuovo componente debba essere istanziato.


3

Trucco per aggiornare gli oggetti di scena se sono 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,
  },
});

3
Penso che lo stato di inizializzazione con oggetti di scena sia anti-pattern, dovrebbe essere evitato. ecco il buon link per leggere github.com/vasanthk/react-bits/blob/master/anti-patterns/… .
prova Hendri il


0

se usi recompose, usa mapPropsper creare nuovi oggetti di scena derivati ​​da oggetti di scena in arrivo

Modifica ad esempio:

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);

si prega di fornire un esempio
vsync
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.