由于mapDispatchToProps函数,如何避免重新渲染连接的React PureComponent?

时间:2017-10-24 12:46:56

标签: javascript reactjs redux

每当调用mapDispatchToProps时,它都会生成要返回的新函数。例如:

const mapDispatchToProps = function(dispatch, ownProps) {
  return {
    addToStack: (episodeId, stackId) => {
      return dispatch(StackAction.addEpisodeToStack(episodeId, stackId));
    },
  };
}

每次调用mapDispatchToProps时,它都会生成一个带有新箭头功能的新对象。

在我的应用程序中,我经常要避免重新渲染我的组件。使用PureComponent通常是可行的方法。但是,由于函数总是不同的,PureComponent将无法帮助,我必须创建一个shouldComponentUpdate策略。在那里,我必须将所有mapDispatchToProps函数“黑名单”并忽略所有这些函数。我必须将每个新函数添加到列表中,以避免重新渲染。

这是黑名单shouldComponentUpdate样板的一个例子:

const blacklist = [
  'addToStack',
]

shouldComponentUpdate(nextProps, nextState) {
  for (let i in nextProps) {
    if (blacklist.includes(i)) continue;
    if (nextProps[i] !== this.props[i]) {
      return true;
    }
  }
  for (let i in nextState) {
    if (nextState[i] !== this.state[i]) {
      return true;
    }
  }
  return false;
}

我想出了一个新的解决方案

const dispatch;
const mapDispatchToPropsFunctions = {
  addToStack: (episodeId, stackId) => {
    return dispatch(StackAction.addEpisodeToStack(episodeId, stackId));
  },
};

const mapDispatchToProps = function(dispatchArg, ownProps) {
  dispatch = dispatchArg
  return mapDispatchToPropsFunctions;
}

这样函数是常量的,不会触发PureComponent的重新渲染,我也不必维护一个shouldComponentUpdate函数。

然而,这对我来说似乎不对。 是否存在处理此问题的“默认”方式?

2 个答案:

答案 0 :(得分:0)

我通常建议尝试重新创建捕获类似道具值的函数,而是在类上使用一个处理程序方法将prop值传递给action创建者。我还建议人们不要直接写mapDispatch个函数,而是使用"对象的简写" connect()

示例:

const actions = {addToStack : StackAction.addEpisodeToStack};

class MyComponent extends React.Component {
    addToStack = () => {
        this.props.addToStack(this.props.episodeId, this.props.stackId);
    }
}

在您的特定代码段中,您似乎甚至无法在mapDispatch中引用任何道具值,因此无需声明ownProps参数。 (connect只会在请求mapDispatch参数时多次调用ownProps函数。否则,只有在创建组件时才调用mapDispatch一次。)

答案 1 :(得分:0)

结果证明,实际的解决方案是根本不使用mapDispatchToProps。 在react-redux docs上隐藏着很多关于速记方法的引用:

  

如果传递了一个对象,则假定该对象内部的每个函数都是一个   Redux动作创建者。具有相同功能名称但具有   每个动作创建者都包裹在调度调用中,因此他们可能是   直接调用,将​​合并到组件的道具中。

因此解决方案是,与其提供一个将分派绑定到动作创建者的函数,不如提供一个连接包含动作创建者的对象作为第二个参数的方法。 Connect只会绑定一次并且始终使用相同的功能,从而避免不必要的重新渲染。

实际上,这应该是为动作创建者提供联系的首选方式,但他们并未在文档中这么说。