web-dev-qa-db-ja.com

componentDidUpdateでのPrevPropsの比較

私は私の心を失っています。多分あなたは私を助けることができます。マウントされたコンポーネントのcomponentDidUpdate内でプロップが変更されたことを検出しようとしています。過去には問題なく動作しました。私はうまく機能しているテスト(以下のコードではrefreshData)さえ持っています。 SOMEHOWがcomponentDidUpdate(prevProps)で検出されない方法で小道具を渡すことは可能ですか?

component.js:

componentDidUpdate(prevProps){

    //works fine
    if ( this.props.refreshData !== prevProps.refreshData ) {
        if ( this.props.refreshData )
            this.refreshData();
    }

    //these two arent calling
    if ( this.props.selectedCountries !== prevProps.selectedCountries ) {
        if ( this.props.selectedCountries )
            console.log('updated selected countries');
    }

    if ( this.props.selectedLocations !== prevProps.selectedLocations ) {
        console.log('updated selected locations');
    }

}

app.jsで次のような小道具を渡します:

selectLocation = (id, type, lng, lat, polydata, name, clear = false) => {

  //console.log(type);
  //console.log(lng);
  //console.log(lat);
  //console.log(polydata);

  let selectedType = 'selected' + type;
  let previousState = [];

  if (clear) {
    this.setState({
      selectedCountries: [],
      selectedLocations: [],
      selectedServices: [],
      selectedPoints: [],
      mapCenter: [lng, lat],
      locationGeoCoords: [polydata]
    })
    previousState.Push(id);

  } else {

    previousState = this.state[selectedType];
    if (previousState.indexOf(id) === -1) {
      //Push id
      previousState.Push(id);

    } else {
      //remove id
      var index = previousState.indexOf(id)
      previousState.splice(index, 1);
    }
  }

  if (type === "Countries") {

    this.setState({
      selectedCountries: previousState,
      refreshData: true,
    })
  } else if (type === "Locations") {
    this.setState({
      selectedLocations: previousState,
      refreshData: true
    })
  } else if (type === "Points") {
    this.setState({
      selectedPoints: previousState,
      refreshData: true
    })
  }


}


render() {
  return (

    <component
      selectedCountries={this.state.selectedCountries}
      selectedLocations={this.state.selectedLocations}
      refreshData={this.state.refreshData} />
  }
}
6
barrylachapelle

こんにちは:)私のコメントで述べたように、問題はApp.jsファイルにあります-配列を変更しています。つまり、受け継ぐために選択した国の新しい配列を作成していると考えている場合、実際には元の配列を更新しているので、比較を行うときは常に2つのまったく同じ配列を比較しています。

App.jsを次のように更新してみてください-

_selectLocation = (id, type, lng, lat, polydata, name, clear = false) => {

  //console.log(type);
  //console.log(lng);
  //console.log(lat);
  //console.log(polydata);

  let selectedType = 'selected' + type;
  let previousState = [];

  if (clear) {
    this.setState({
      selectedCountries: [],
      selectedLocations: [],
      selectedServices: [],
      selectedPoints: [],
      mapCenter: [lng, lat],
      locationGeoCoords: [polydata]
    })
    previousState.Push(id);

  } else {

    previousState = [].concat(this.state[selectedType]);
    if (previousState.indexOf(id) === -1) {
      //Push id
      previousState.Push(id);

    } else {
      //remove id
      var index = previousState.indexOf(id)
      previousState.splice(index, 1);
    }
  }

  if (type === "Countries") {

    this.setState({
      selectedCountries: previousState,
      refreshData: true,
    })
  } else if (type === "Locations") {
    this.setState({
      selectedLocations: previousState,
      refreshData: true
    })
  } else if (type === "Points") {
    this.setState({
      selectedPoints: previousState,
      refreshData: true
    })
  }


}


render() {
  return (

    <component
      selectedCountries={this.state.selectedCountries}
      selectedLocations={this.state.selectedLocations}
      refreshData={this.state.refreshData} />
  }
}_

唯一の違いは、あなたがpreviousStateを設定した行です-私はそれを次のように更新しました

previousState = [].concat(this.state[selectedType]);

_[].concat_を追加することにより、毎回新しい配列を効率的に作成しているので、Push/spliceを介して配列に変更を適用すると、新しい配列のみが変更されます。 。その後、小道具としてそれを渡すと、比較は正しく機能します:)

あなたの読書の興味のために、これについて少し話す記事を見つけました: https://medium.com/pro-react/a-brief-talk-about-immutability-and-react-s-helpers- 70919ab8ae7c

6
Rose Robertson

selectedCountriesselectedLocationsは配列オブジェクトです。それの参照は決して変更されません。代わりに、長さを確認してください。

componentDidUpdate(prevProps){

    if ( this.props.refreshData !== prevProps.refreshData ) {
        if ( this.props.refreshData )
            this.refreshData();
    }

    if ( this.props.selectedCountries.length > prevProps.selectedCountries.length ) {
        if ( this.props.selectedCountries )
            console.log('updated selected countries');
    }

    if ( this.props.selectedLocations.length > prevProps.selectedLocations.length ) {
        console.log('updated selected locations');
    }
}

上記のコードスニペットでは、this.stateを直接変更しているようです。状態は不変である必要があります。状態を元の配列に変更するのではなく、新しい配列を作成するときに、要素を追加する場合はconcatを、削除する場合はfilterを必ず確認してください。私はこれらの行で何かをします。

また、コンポーネント名を大文字にすることもお勧めします。

selectLocation = (id, type, lng, lat, polydata, name, clear = false) => {
        //console.log(type);
        //console.log(lng);
        //console.log(lat);
        //console.log(polydata);

        let selectedType = "selected" + type;
        let previousState = [];
        let updatedData = [];

        if (clear) {
          this.setState({
            selectedCountries: [],
            selectedLocations: [],
            selectedServices: [],
            selectedPoints: [],
            mapCenter: [lng, lat],
            locationGeoCoords: [polydata]
          });
        } else {
          const data = this.state[selectedType];
          if (data.indexOf(id) === -1) {
            //Push id
            updatedData = [...data, id];
          } else {
            updatedData = data.filter((value) => value !== id);
          }
        }

        if(type) {
          this.setState({
            [selectedType]: updatedData,
            refreshData: true
          });
        }
      };

      render() {
        return (
          <component
            selectedCountries={this.state.selectedCountries}
            selectedLocations={this.state.selectedLocations}
            refreshData={this.state.refreshData}
          />
        );
      }
    }
2
Sushanth --

場所と国の小道具が実際に変化していることを確認しましたか?はいの場合、次のコードが機能するはずです。

componentDidUpdate(prevProps) {
  if (this.props.selectedCountries.length !== prevProps.selectedCountries.length) {
    console.log("updated selected countries");
  }

  if (this.props.selectedLocations.length !== prevProps.selectedLocations.length) {
    console.log("updated selected locations");
  }
}

ここに効果を紹介するためのフィドルを作成しました: https://codesandbox.io/s/o580n8lnv5

0
grenzbotin