Kann ich die Requisiten einer Komponente in React.js aktualisieren?

217

Nach dem Beginn der Arbeit mit React.js scheint propses statisch zu sein (von der übergeordneten Komponente übergeben), während stateÄnderungen auf Ereignissen basieren. Ich habe jedoch in den Dokumenten einen Verweis auf bemerkt componentWillReceiveProps, der speziell dieses Beispiel enthält:

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

Dies scheint zu implizieren, dass sich die Eigenschaften einer Komponente basierend auf dem Vergleich von nextPropszu ändern können this.props. Was vermisse ich? Wie ändern sich Requisiten oder irre ich mich darüber, wo dies genannt wird?

Matt Huggins
quelle

Antworten:

249

Eine Komponente kann ihre eigenen Requisiten nur aktualisieren, wenn es sich um Arrays oder Objekte handelt (wenn eine Komponente ihre eigenen Requisiten aktualisiert, auch wenn dies ein Anti-Pattern ist), kann sie jedoch ihren Status und die Requisiten ihrer untergeordneten Elemente aktualisieren.

Ein Dashboard hat beispielsweise ein speedFeld in seinem Status und übergibt es an ein untergeordnetes Messgerät, das diese Geschwindigkeit anzeigt. Seine renderMethode ist gerecht return <Gauge speed={this.state.speed} />. Wenn das Dashboard aufruft this.setState({speed: this.state.speed + 1}), wird die Anzeige mit dem neuen Wert für neu gerendert speed.

Kurz bevor dies geschieht, wird Gauge's componentWillReceivePropsaufgerufen, damit das Gauge den neuen Wert mit dem alten vergleichen kann.

Valéry
quelle
Es hört sich also so an, als würde es einmal aufgerufen, wenn die React-Komponente initialisiert wird und Requisiten empfängt. Die Requisiten "ändern" sich nicht wirklich, sobald eine Komponente erstellt wurde. Ist das richtig?
Matt Huggins
12
Das Gegenteil. In der Dokumentation heißt es: "Wird aufgerufen, wenn eine Komponente neue Requisiten empfängt. Diese Methode wird beim ersten Rendern nicht aufgerufen."
Valéry
Vielen Dank. Diese Frage ergab sich aus einem anfänglichen Missverständnis von React dahingehend, dass eine Komponente beim erneuten Rendern des Bildschirms (oder eines Teils des Bildschirms) wiederverwendet wird.
Matt Huggins
1
Ja. Eine Komponente kann ein Ereignis abhören und seinen Status jedes Mal aktualisieren, wenn das Ereignis ausgelöst wird.
Valéry
8
Ich komme aus der Zukunft: componentWillReceivePropsist jetzt veraltet: und ersetzt durch eine Kombination von getDerivedStateFromPropsund componentDidUpdate.
bvdb
53

REQUISITEN

Eine React-Komponente sollte Requisiten verwenden, um Informationen zu speichern, die geändert werden können, aber nur von einer anderen Komponente geändert werden können.

ZUSTAND

Eine React-Komponente sollte den Status verwenden, um Informationen zu speichern, die die Komponente selbst ändern kann.

Ein gutes Beispiel liefert bereits Valéry.

Ali Adravi
quelle
4
@ali_adravi werden diese Zitate von irgendwoher kopiert? Wenn ja, wie lautet die Referenz? Oder sind das Ihre Worte, und Sie haben sie nur als Anführungszeichen formatiert?
Rob Bednark
@RobBednark Ich erinnere mich jetzt nicht an die genaue Quelle, aber sicher ist das eine wahre Aussage mit ein wenig Änderung im Satz aus einem Buch.
Ali Adravi
26

Requisiten können sich ändern, wenn das übergeordnete Element einer Komponente die Komponente erneut mit unterschiedlichen Eigenschaften rendert. Ich denke, dies ist meistens eine Optimierung, so dass keine neue Komponente instanziiert werden muss.

Joost Diepenmaat
quelle
3

Trick, um Requisiten zu aktualisieren, wenn sie Array sind:

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
quelle
3
Ich denke, dass das Initialisieren des Zustands mit Requisiten ein Anti-Muster ist und vermieden werden sollte. Hier ist der gute Link zum Lesen von github.com/vasanthk/react-bits/blob/master/anti-patterns/… .
TryHendri
0

Wenn Sie verwenden recompose, verwenden SiemapProps , um neue Requisiten zu erstellen, die von eingehenden Requisiten abgeleitet sind

Bearbeiten Sie zum Beispiel:

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
quelle
Bitte geben Sie ein Beispiel
vsync