首页 > 解决方案 > Memoize Reselect 选择器输出基于单个输入选择器而不是全部

问题描述

我有一个重新选择选择器,它将一组选定的 id 映射到规范化存储中的对象。

const activeObjectsSelector = createSelector(
  state => state.activeIds,
  state => state.objects.byId,
  (activeIds, objectsById) => activeIds.map(id => objectsById[id])
)

问题是它会破坏缓存并在新对象添加到规范化存储时重新运行,因为值发生了state.objects.byId变化。我关心破坏缓存的唯一变化是state.activeIds. 这可能吗?

标签: javascriptreduxreselect

解决方案


您可以为此使用 reselect 的 defaultMemoize 来记忆地图的结果,方法是将其传递给一个记忆函数,该函数将数组的项目作为参数:

const { createSelector, defaultMemoize } = Reselect;
const state = {
  activeIds: [1, 2],
  objects: {
    1: { name: 'one' },
    2: { name: 'two' },
    3: { name: 'three' },
  },
};
const selectActiveIds = (state) => state.activeIds;
const selectObjects = (state) => state.objects;
const createMemoizedArray = () => {
  const memArray = defaultMemoize((...array) => array);
  return (array) => memArray.apply(null, array);
};
const createSelectAcitiveObjects = () => {
  const memoizedArray = createMemoizedArray();
  return createSelector(
    selectActiveIds,
    selectObjects,
    (ids, objects) =>
      memoizedArray(ids.map((id) => objects[id]))
  );
};
const selectAcitiveObjects = createSelectAcitiveObjects();
const one = selectAcitiveObjects(state);
console.log('one is:',one);
const two = selectAcitiveObjects(state);
console.log('one is two', two === one);
const newState = { ...state, activeIds: [1, 2, 3] };
const three = selectAcitiveObjects(newState);
console.log('three is two', three === two);
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>


<div id="root"></div>


推荐阅读