【问题标题】:Preventing component updates from multiple props in react在反应中防止来自多个道具的组件更新
【发布时间】:2017-05-17 07:50:44
【问题描述】:

我有一个 react/redux 应用程序,它有一个 recharts 图表,当数据更改时会显示动画。

我正在使用Redux,而我的大部分操作只更改了一个state 属性,这会导致一个props 传递。但是,我的一些操作现在使用thunks 进行一些异步操作并调用其他操作。

例如,我可能有一个动作getChartData,当用户选择一个轴时会调用它。

export let getChartData = axis => dispatch => {
  // trimmed for brevity
  fetchJSON(url).then(data => {
    dispatch(dataRetrievalSuccess(data));
    dispatch(updateSelectedAxis(axis));
  }).catch(error => {
    dispatch(dataRetrievalError(error));
  });
};

在此示例中,updateSelectedAxis 值将更改负责显示当前选定轴的本地状态属性,dataRetrievalSuccess 函数将负责将props.data 传递给图表。

我要解决的问题是防止图表在组件的 selectedAxis 道具发生变化但数据没有变化时更新。

我以为我可以使用componentWillRecieveProps 之类的东西,但我在上面的thunk 示例中遇到的问题是,当我调用具有相同数据的dataRetrievalSuccess 时,我接到了一个componentWillRecieveProps 的电话在this.props.datanextProps.data 中,所以我可以阻止更新。但是,当我随后调用updateSelectedAxis 时,我没有将data 作为道具的一部分,因为它已经改变了,所以我无法根据这两个值执行逻辑操作。

我认为这可能是一个排序问题,但即使我将它打包成一个动作,我仍然会得到多个道具设置。

我可以通过将数据和轴的变化打包成一个对象来解决这个问题吗? 我不太确定从架构上解决这个问题的最佳方式,并欢迎任何建议。

编辑: 稍微扩展一下,我正在调度两个动作,它们都会改变自己的状态位,从而导致两次渲染。

我试过这样写:

shouldComponentUpdate(nextProps, nextState) {
  if(this.dataHasChanged(nextProps)) {
    return true;
  }
  return false;
}

这几乎可以工作,但每次图表显示的数据都会落后于它需要的位置。

【问题讨论】:

  • shouldComponentUpdate(nextProps, nextState) 呢?
  • 你提到的这个单一状态属性由DATA和AXIS组成?在其他世界中,在全局状态下您可以访问这些变量吗? (并且它可以通过 this.props 访问你传递给组件?我错过了那部分。如果你可以访问这两个对象,你可以使用 componentShouldUpdate 函数:>
  • @DennisStücken 问题在于我收到了对该函数的两次调用,一次调用数据,一次调用轴更改,我需要两者都确定是否应该更新图表动画。
  • @MariuszJasinski 我似乎一次只能访问一个属性。两次运行 shouldComponentUpdate 函数,一次使用数据,另一次使用轴。它本身不足以让我知道我是否应该更新组件。我想组合成一个对象可以让我这样做,但这是最好的方法吗?
  • 现在我明白了@dougajmcdonald。您调度 2 个动作,这两个动作中的每一个都会更改状态(因此会发生渲染),并且您无权访问第二个动作的新版本。是的,将这两者结合起来肯定会有所帮助。我有一个想法:think action的第二个参数是getState函数。您可以通过调用此获取当前状态,并比较实际轴/数据是否与接收到的不同,并且取决于该调度某些操作:)

标签: reactjs redux redux-thunk


【解决方案1】:

您可以使用 thunk 访问 action creator 下的 store 的当前状态(因为 thunk 会为您注入状态。),然后将 ajax 响应数据与之前的状态数据进行比较以调度新的操作。

 export let getChartData = axis => (getState, dispatch) => {
          // trimmed for brevity
          fetchJSON(url).then(data => {
           if(getState().data !== data){
            dispatch(dataRetrievalSuccess(data));
            dispatch(updateSelectedAxis(axis));
            }
          }).catch(error => {
            dispatch(dataRetrievalError(error));
          });
        };

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 1970-01-01
    • 2021-02-22
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多