webentwicklung-frage-antwort-db.com.de

Wann ist die Lifecycle-Methode von componentWillReceiveProps zu verwenden?

Ich bin neu bei React/Redux und habe ein Problem mit dem Zustand.

TrajectContainer.jsx

class TrajectContainer extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            trajects: props.trajects,
            onClick: props.onClick
        };
    }

    componentWillReceiveProps(nextProps) {
        console.log('componentWillReceiveProps', nextProps);
        this.setState(nextProps);
    }

    render() {
        // When the componentWillReceiveProps is not present, the this.state will hold the old state
        console.log('rerender', this.state);
        return (<div className="col-md-6">
            <h2>Trajects</h2>
            <button className="btn btn-primary" onClick={this.state.onClick}>Add new Traject</button>
            {this.state.trajects.map(traject => <Traject traject={traject} key={traject.name}/>)}
        </div>)
    }
}

const mapStateToProps = function (store) {
    console.log('mapToStateProps', store);
    return {
        trajects: store.trajects
    };
};

const mapDispatchToProps = function (dispatch, ownProps) {
    return {
        onClick: function () {
            dispatch(addTraject());
        }
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(TrajectContainer);

Wenn ein Reduzierer einen neuen Status zurückgibt, wird die Komponente mit den neuen Daten erneut gerendert.

Allerdings: Wenn ich die ComponentWillReceiveProps-Funktion entferne, hat die render () - Funktion den alten Zustand.

Ich habe die in mapStateToProps empfangenen Daten überprüft, und dies ist der neue Zustand New ... So verstehe ich nicht, warum ich die Funktion componentWillReceiveProps brauche, damit die Renderfunktion die neuen Daten erhält.

Mache ich etwas falsch?

8
Mazzy

componentWillReceiveProps ist erforderlich, wenn Sie die Statuswerte mit neuen Props-Werten aktualisieren möchten. Diese Methode wird aufgerufen, wenn sich die Props-Werte ändern.


Warum benötigen Sie in diesem Fall diese Methode von ComponentWillReceiveProps?

Weil Sie die Requisitenwerte in der Statusvariablen speichern und wie folgt verwenden: 

this.state.KeyName

Aus diesem Grund benötigen Sie die componentWillReceiveProps-Lebenszyklusmethode, um den Statuswert mit dem neuen Wert für props zu aktualisieren. Nur die Requisent-Werte der Komponente werden aktualisiert, aber automatisch wird der Status nicht aktualisiert. Wenn Sie den Status nicht aktualisieren, hat this.state immer die ursprünglichen Daten.

componentWillReceiveProps ist nicht erforderlich, wenn Sie die Requisitenwerte nicht im Status speichern und direkt verwenden: 

this.props.keyName

Reagiert jetzt immer aktualisierte Requisitenwerte innerhalb der Render-Methode. Wenn Requisiten geändert werden, wird die Komponente mit neuen Requisiten erneut gerendert.

Gemäß DOC:

componentWillReceiveProps () wird vor einer gemounteten Komponente aufgerufen erhält neue Requisiten. Wenn Sie den Status als Antwort auf .__ aktualisieren müssen. Prop-Änderungen (z. B. um sie zurückzusetzen), können Sie this.props .__ vergleichen. und nextProps und führen Sie Zustandsübergänge mithilfe von this.setState () in .__ durch. diese Methode. 

React ruft während .__ keine KomponenteWillReceiveProps mit ersten Requisiten auf. Montage. Es ruft diese Methode nur auf, wenn einige Requisiten der Komponente aktualisieren.

Vorschlag:

Speichern Sie die Requisitenwerte nicht im Status, verwenden Sie direkt this.props und erstellen Sie die UI-Komponenten.

23
Mayank Shukla

Ich hatte ein ähnliches Problem wie withRouter():

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(TrajectContainer));
2

Das Problem bei Ihrer Implementierung ist, dass Sie Ihren Redux-Store-Status (der von den Requisiten kommt) in Ihren React-Status (this.state) duplizieren.

Wenn in Ihrem Beispiel store.trajects aktualisiert wird, wird this.props.traject aktualisiert, und ein Rendering wird nur ausgelöst, wenn this.props.traject in Ihrer Render-Methode verwendet wird (dies ist nicht der Fall).

Da Sie in Ihrer Render-Methode den Status anstelle der Requisite verwenden, müssen Sie den Status Ihrer Komponente manuell mit this.setState ändern, um ein Rendering auszulösen.

Dies ist kein gutes Muster: Ich würde raten, den Staat nicht zu verwenden und die Requisiten direkt wie folgt zu verwenden:

class TrajectContainer extends React.Component {
    render() {
        return (<div className="col-md-6">
            <h2>Trajects</h2>
            <button className="btn btn-primary" onClick={this.props.onClick}>Add new Traject</button>
        {this.props.trajects.map(traject => <Traject traject={traject} key={traject.name}/>)}
    </div>)
}
}
const mapStateToProps = function (store) {
  console.log('mapToStateProps', store);
  return {
    trajects: store.trajects
  };
};

const mapDispatchToProps = function (dispatch, ownProps) {
   return {
      onClick: function () {
        dispatch(addTraject());
      }
  }
};

export default connect(mapStateToProps, mapDispatchToProps)(TrajectContainer)
1

Hier gibt es zwei mögliche Probleme

  1. Ordnen Sie Ihre Requisiten nicht erneut zu, um anzugeben, dass Sie redux verwenden, um die Werte aus dem Laden zu ziehen und als Requisiten an Ihre Komponente zurückzugeben

Das Vermeiden von Status bedeutet, dass Sie Ihren Konstruktor oder Lebenszyklusmethoden nicht mehr benötigen. Damit Ihre Komponente als zustandslose Funktionskomponente geschrieben werden kann, bietet das Schreiben Ihrer Komponente auf diese Weise Performance-Vorteile.

  1. Sie müssen Ihre Aktion nicht in den Versandmodus packen, wenn Sie mapDispatcahToProps übergeben. Wenn ein Objekt übergeben wird, wird davon ausgegangen, dass es sich bei jeder Funktion um einen Aktionsersteller handelt. Ein Objekt mit den gleichen Funktionsnamen, wobei jedoch jeder Aktionsersteller in einen Dispatch eingebunden wird

Nachfolgend finden Sie ein Code-Snippet, das den Status Ihrer Komponente entfernt und sich auf den Status bezieht, der vom Redux-Store zurückgegeben wurde 

import React from "react";
import { connect } from "react-redux";

const TrajectContainer = ({ trajects, addTraject }) => (
	<div className="col-md-6">
		<h2>Trajects</h2>
		<button className="btn btn-primary" onClick={addTraject}>Add new Traject</button>
		{trajects.map(traject => <Traject traject={traject} key={traject.name} />)}
	</div>
);

const mapStateToProps = ({ trajects }) => ({ trajects });

export default connect( mapStateToProps, { addTraject })(TrajectContainer);

1
user1095118

In Ihrem Fall benötigen Sie componentWillReceiveProps und müssen den Status aktualisieren, wenn Sie neue Requisiten erhalten. weil

  • In Ihrem Konstruktor haben Sie Ihren Status wie folgt erklärt. Wie Sie sehen, konstruieren Sie Ihre state mit den übergebenen Requisiten. (Deshalb benötigen Sie componentWillReceiveProps und die Logik, um sie dort zu aktualisieren)

    this.state = {
        trajects: props.trajects,
        onClick: props.onClick
    };
    
  • Wenn also Ihre Requisiten geändert werden, ist componentWillReceiveProps die Funktion, die aufgerufen wird. Der Konstruktor wird nicht aufgerufen. Sie müssen also den Status erneut setzen, damit die Änderungen in den Status der Komponente übergehen.

  • Ihre Logik sollte jedoch wie folgt sein. Mit einer Bedingung, mit der Sie wiederholte Statusaktualisierungen verhindern können, wenn sie mehrfach aufgerufen wird.

    componentWillReceiveProps(nextProps) {
     console.log('componentWillReceiveProps', nextProps);
     if (this.props !== nextProps) {
      this.setState(nextProps);
     }
    }
    

Sie sollten die Requisiten nur dann im Zustand speichern, wenn Sie den Inhalt ändern. Aber in Ihrem Fall sehe ich, dass es keine Modifikation gibt. So können Sie this.props.trajects direkt verwenden, anstatt es im Zustand zu speichern und dann zu verwenden. Auf diese Weise können Sie die componentWillReceivePropsSo loswerden, so dass Ihre Renderfunktion etwa Folgendes verwendet

{this.props.trajects.map(traject => //what ever is your code.... }
0
Panther