【问题标题】:Component updates even though prop has not changed即使 prop 没有更改,组件也会更新
【发布时间】:2019-03-06 00:11:03
【问题描述】:

我有一个从父组件获取数据的 MapBox 组件。

我试图避免每次父组件中发生状态更改时更新组件。即使 shouldComponentUpdate 记录相同的道具,它也会更新...

地图儿童

    componentDidMount(){
        if(this.props.data.features !== null){
            this.fetchMap();
        }
    }

    shouldComponentUpdate(nextProps) {
        console.log('now:', this.props.data)
        console.log('next', nextProps.data)
        if (this.props.data === nextProps.data) {
            return false;
        }
        if (this.props.data !== nextProps.data) {
            return true;
        }
        return false;
    }
    componentDidUpdate(prevProps) {
        if (this.props.data !== prevProps.data) {
            this.fetchMap();
        }
    }
    fetchMap() {
        const { data } = this.props
        const map = new mapboxgl.Map({
            container: this.mapContainer,
            style: 'mapbox://styles/mapbox/light-v9',
            center: [8.32, 60.44],
            zoom: 5,
        })

        map.on('load', () => {

                map.addSource('locations', {
                    type: 'geojson',
                    data
                });
        });
    }

   .... render and return bla bla

家长:

const Parent () => {
   const [state, change] = useState(false)
   return (
     <Button onClick={change(!state)}>Sorter</Button> // click and <Map> rerenders
     <Map setDraw={setDraw} data={geojson} />
   )
}

【问题讨论】:

  • 不要尝试===比较,而是尝试shallowCompare或使用React.PureComponent,看看是否有帮助。
  • 简化这个` if (this.props.data === nextProps.data){return false;} if(this.props.data !== nextProps.data) {return true;}`返回this.props!==nextProps
  • @Panther 我尝试更改为React.PureComponent 并删除shouldComponentUpdate。它仍然重新渲染。浅比较不是一回事吗?
  • 那么是调试的好时机。基本上你需要编写自己的浅表比较,看看哪些 props 发生了变化,它们为什么会发生变化以及如何避免它。
  • @Panther 最好的前进方式是什么?可能是因为数据对象比较大而且嵌套比较大,所以不理解没有区别?

标签: javascript reactjs mapbox mapbox-gl-js


【解决方案1】:

我有 3 种方法来实现它

1 父调用状态使用回调函数方式,强制对象进入一个新的对象。

this.setState((state) => { 
return  {...state};
 });

您可以在以下位置查看此 api:https://reactjs.org/docs/react-component.html#setstate

2深度比较意味着你需要对数组中的项目一个一个的检查。或者暴力,我将数组或对象变成字符串然后比较。

3 您可以为数组中的每个项目创建组件,然后比较每个组件的差异。

const geojson = {
    id:0,// +1 when changed
    type: "FeatureCollection",
    features: locations
};
shouldComponentUpdate(nextProps) {// becacuse nextProps are always a different object from props
    if (this.props.data.id === nextProps.data.id) {
      return false;
    }else{
      return true;
    }
}

【讨论】:

  • 我不太确定如何实现您所说的第三个选项。你能举个例子吗?
  • 对不起,我误解了你的代码。第三个不适合你。你如何在父母中设置状态你可以显示它吗?我认为第一个可以解决它。
  • 我使用钩子设置状态。例如const [state, change] = useState(false),然后通过change(!state) 更改状态。
  • 尝试使用功能更新,reactjs.org/docs/hooks-reference.html#functional-updates。我认为您所做的更改会返回相同的对象。
  • 我注意到它并没有真正重新渲染。它闪烁并重新初始化地图。如果状态更改发生在同一组件中,则不会发生这种情况。仅当更改发生在父组件中时才会发生。
猜你喜欢
  • 2013-02-12
  • 1970-01-01
  • 2021-07-26
  • 2017-11-30
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 2013-08-30
相关资源
最近更新 更多