比较componentDidUpdate中的PrevProps

时间:2018-09-18 19:10:47

标签: reactjs react-props

我迷失了方向。也许你可以帮我。我试图检测道具何时已更改已安装组件的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} />
  }
}

3 个答案:

答案 0 :(得分:2)

嗨:),正如我的评论中所述,问题出在您的App.js文件中-您正在对数组进行变异。换句话说,当您想创建一个新的选定国家/地区数组以传递时,实际上是在更新原始数组,因此当您进行比较时,总是会比较两个完全相同的数组。

尝试像这样更新您的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,我每次都会有效地创建一个NEW数组,因此,当您通过push / splice对数组应用更改时,您将只修改NEW数组。然后,将比较作为道具传递下来后,比较就可以正常工作了:)

出于您的阅读兴趣,我发现了一篇有关此内容的文章:https://medium.com/pro-react/a-brief-talk-about-immutability-and-react-s-helpers-70919ab8ae7c

答案 1 :(得分:1)

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 :(得分:0)

您确定地点和国家/地区的道具确实在改变吗?如果是,则以下代码应该起作用:

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