【问题标题】:How to prevent component re-render while using redux/reselect?使用 redux/reselect 时如何防止组件重新渲染?
【发布时间】:2019-05-26 23:02:53
【问题描述】:

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

组件 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;
};

【问题讨论】:

  • 什么是“组件 A”和“组件 B”?
  • 使用 MakeMapStateToProps 的组件实例 - 只是试图限制问题中的代码量。
  • 你在 A 和 B 中都使用makeMapStateToProps 吗?
  • 是的,两者都使用。

标签: reactjs redux react-redux reselect


【解决方案1】:

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

如果组件所需的对象内部状态未发生变化,则 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;
    }
  );

希望这对将来的某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2021-01-07
    • 2021-12-05
    • 2021-05-24
    • 1970-01-01
    相关资源
    最近更新 更多