首页 > 解决方案 > 使用 redux/reselect 时如何防止组件重新渲染?

问题描述

我收到了对我的状态的频繁更新,这会导致在未访问不断变化的状态属性的组件中出现一些不需要的重新渲染。

组件 A 和 B 的创建方式相同,组件 A 具有 valueKeys ['speed', 'time'],组件 B 没有 valueKeys []。

当速度和时间更新时,每个数组都会再添加一个值,组件 A 会按预期重新渲染,但组件 B 也会重新渲染。

我认为这是因为 makeValuesSelector 参考的 valuesSelector 输入正在改变?尽管该值是一个空数组。

有什么办法可以防止组件 B 在这种情况下重新渲染?

状态

{
 speed: [ 5, 4, 6],
 time: [ 1, 2, 3]
}

值键

[ 'speed', 'time']

选择器

const valuesSelector = state => state.values;
const keysSelector= (state, props) => props.valueKeys;

const makeValuesSelector = () =>
  createSelector(
    [valuesSelector, keysSelector],
    (values, keys) => {
      let usedValues = {};
      keys.forEach(key => {
        if (values[key]) {
          usedValues[key] = values[key];
        }
      });
      return usedValues;
    }
  );

零件

const makeMapStateToProps = () => {
  const valuesSelector = makeValuesSelector();
  const mapStateToProps = (state, props) => ({
    values: valuesSelector(state, props),
  });
  return mapStateToProps;
};

标签: reactjsreduxreact-reduxreselect

解决方案


一段时间后,我又回到了这个问题,因为它造成了严重的性能瓶颈。我通过在选择器中使用自定义相等检查来检查状态内的对象是否已更改,从而解决了这个问题。

如果组件需要的对象内部状态没有改变,则 makeValuesSelector 将不会运行,因为自定义相等检查阻止了它。由于 makeValuesSelector 尚未运行,因此它将阻止组件重新渲染。关于我上面描述的情况,组件 B 不会重新渲染。

const valuesSelector = state => state.values;
const keysSelector= (state, props) => props.valueKeys;

const equalityCheckShallow = (currentVal, previousVal) => {
  let noUpdate = true;
  Object.keys(currentVal).forEach(key => {
    if (currentVal[key] !== previousVal[key]) {
      noUpdate = false;
    }
  });
  return noUpdate;
};

const createSelectorWithShallowCompare = createSelectorCreator(defaultMemoize, equalityCheckShallow);

const makeValuesSelector = () =>
  createSelectorWithShallowCompare(
    [valuesSelector, keysSelector],
    (values, keys) => {
      let usedValues = {};
      keys.forEach(key => {
        if (values[key]) {
          usedValues[key] = values[key];
        }
      });
      return usedValues;
    }
  );

希望这可以帮助将来的人。


推荐阅读