在Redux中记忆一个过滤数组

问题描述 投票:1回答:1

我设置了以下选择器

选择器.js

const getNodeHistory = (state) => state.session.nodeHistory;
const getUnit = (state, unit) => unit;

export const selectNodeHistory = createSelector(
    [getNodeHistory, getUnit],
    (history, unit) => history.filter((h) => h.unit === unit)
);

控件

const nodeHistory = useSelector((state) => selectNodeHistory(state, unit));

然而,每一个使用selectNodeHistory的组件在state.session.nodeHistory发生变化时都会重新渲染,即添加或更改了一个新的项目,即使该项目不属于被过滤的选择器。

不知道是我做错了什么,还是使用这个方法不可能。

reactjs react-redux memoization reselect
1个回答
0
投票

我将做一个选择器创建器,将库里的 unit 参数。我假设单位来自于道具,如果单位改变或历史改变,组件要重新计算。

const getNodeHistory = (state) => state.session.nodeHistory;

export const createSelectNodeHistory = (unit) =>// curry unit parameter
  createSelector([getNodeHistory], (history) =>
    history.filter((h) => h.unit === unit)
  );

const Component = ({ unit }) => {
  //memoize the selector (re create when unit changes)
  //  here memoization of unit parameter is done in component
  //  so each component has their own memoized selector
  const selectNodeHistory = React.useMemo(
    () => createSelectNodeHistory(unit),
    [unit]
  );
  const nodeHistory = useSelector(selectNodeHistory);
};

在这个例子中,每个组件都会有自己的选择器。你也可以将备忘逻辑移到创建选择器的代码中,但是如果你使用这个选择器渲染多个具有不同单元值的组件,那么什么都不会被备忘,因为它们都共享同一个选择器。

//moved memoizing to create selector, memoization or unit is shared
//  for all components calling createSelectNodeHistory
export const createSelectNodeHistory = createSelector(
  (unit) => unit,
  (unit) =>
    createSelector([getNodeHistory], (history) =>
      history.filter((h) => h.unit === unit)
    )
);

const Component = ({ unit }) => {
  //create memoized selector, will be re created when
  //  unit changes. Because memoization of unit is shared by
  //  all components nothing will be memoized when you do
  //  <Component unit={1} /><Component unit={2} />
  const selectNodeHistory = createSelectNodeHistory(unit);
  const nodeHistory = useSelector(selectNodeHistory);
};

现在来解决我们的问题;当nodeHistory发生变化,但该变化并没有影响history.filter时,你可以像这样将filter结果备忘化 本回答 在你的情况下,代码应该是这样的。

const createMemoizedArray = () => {
  const memArray = defaultMemoize((...array) => array);
  return (array) => memArray.apply(null, array);
};

export const createSelectNodeHistory = createSelector(
  (unit) => unit,
  (unit) => {
    const memArray = createMemoizedArray();
    return createSelector([getNodeHistory], (history) =>
      memArray(history.filter((h) => h.unit === unit))
    );
  }
);

或者像这样,如果每个组件都需要自己的memomized选择器。

export const createSelectNodeHistory = (
  unit // curry unit parameter
) => {
  const memArray = createMemoizedArray();
  return createSelector([getNodeHistory], (history) =>
    memArray(history.filter((h) => h.unit === unit))
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.