代码之家  ›  专栏  ›  技术社区  ›  barrylachapelle

比较componentDidUpdate中的prevProps

  •  2
  • barrylachapelle  · 技术社区  · 6 年前

    我疯了。也许你能帮我。我试图检测安装组件的componentDidUpdate中的道具何时发生了更改。它过去工作得很好。我甚至有一个测试(刷新下面代码中的数据)工作正常。是否可能以组件didUpdate(prevProps)未检测到的方式传递props??

    在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 回复  |  直到 6 年前
        1
  •  1
  •   Rose Robertson    6 年前

    您好:)正如我在评论中提到的,这个问题出现在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 我每次都有效地创建一个新数组,因此当您通过 push / splice 您将只修改新数组。一旦你把它作为道具传下去,这个比较就会正常工作。

    为了你的阅读兴趣,我找到了一篇关于这方面的文章: https://medium.com/pro-react/a-brief-talk-about-immutability-and-react-s-helpers-70919ab8ae7c

        2
  •  1
  •   dance2die    6 年前

    selectedCountries selectedLocations 是数组对象。它的引用永远不会改变。而是检查长度。

    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}
              />
            );
          }
        }
    
        3
  •  0
  •   dance2die    6 年前

    您是否确定地点和国家的道具确实在变化?如果是,则应使用以下代码:

    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