如何正确使用createSelector来记忆映射到对象的选择器

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

我有这个选择器:

const selectListOfApplicationIdAndApplicationCompany = state => Object.values(state.applications.dict).map((x) => ({"id": x.id, "companyName": x.companyName}));

我收到来自 React 的警告,说应该记住该选择器,因为它为相同的输入参数返回不同的对象。我明白为什么会发生这种情况。我开始阅读有关 createSelector 的 Redux 文档。我确实阅读了他们的简单示例,但我仍然不明白如何记住我拥有的选择器。

我尝试这样做:

export const selectListOfApplicationIdAndApplicationCompany = createSelector([_selectListOfApplicationIdAndApplicationCompany], (data) => data);

即返回一个“结果函数返回其自己的输入而不进行修改。例如

createSelector([state => state.todos], todos => todos)
这可能会导致记忆效率低下和不必要的重新渲染。 确保转换逻辑位于结果函数中,提取逻辑位于输入选择器中。”警告。

文档讨论了“输入选择器”和“输出选择器”。我不明白我的原始选择器的哪一部分是输入和输出,或者即使我可以将该选择器分成两部分......

javascript redux redux-selector
1个回答
0
投票

结果函数未经修改地返回其自己的输入。例如

createSelector([state => state.todos], todos => todos)

这只是告诉您一个反模式,创建的选择器与直接使用

state => state.todos
选择器函数没有做任何不同的事情,并且在某些情况下可能会导致性能不佳。

文档讨论了“输入选择器”和“输出 选择器”。我不明白我的原始选择器的哪一部分是什么 输入和输出,或者即使我可以将该选择器分成两个 零件。

鉴于以下情况:

const _selectListOfApplicationIdAndApplicationCompany =
  state => Object.values(state.applications.dict)
    .map((x) => ({
      "id": x.id,
      "companyName": x.companyName
    })
  );

export const selectListOfApplicationIdAndApplicationCompany = createSelector(
  [_selectListOfApplicationIdAndApplicationCompany],
  (data) => data
);

传递给选择器数组

createSelector
的第一个参数是输入选择器,例如
_selectListOfApplicationIdAndApplicationCompany
以及数组中的任何其他选择器,最后一个参数是输出,例如计算要记忆的值的结果函数。

确保转换逻辑在结果函数中,并且提取 逻辑位于输入选择器中。

这意味着输入选择器应该选择状态或另一个选择器的输出,并且结果函数应该完成这项工作,例如给定输入计算新值。

将代码更新为如下所示:

export const selectApplicationsDict = state => state.applications.dict;

export const selectListOfApplicationIdAndApplicationCompany = createSelector(
  [selectApplicationsDict],
  (applicationsDict) => Object.values(applicationsDict)
    .map(({ companyName, id }) => ({ companyName, id }),
);

或者您可以将其分解以获得更细的粒度和记忆

export const selectApplications = state => state.applications;

export const selectApplicationsDict = createSelector(
  [selectApplications],
  (applications) => applications.dict,
);

export const selectListOfApplicationIdAndApplicationCompany = createSelector(
  [selectApplicationsDict],
  (applicationsDict) => Object.values(applicationsDict)
    .map(({ companyName, id }) => ({ companyName, id }),
);

记忆选择器以及输入和输出的基本要点是,仅当输入发生变化并且需要重新计算和记忆输出时才调用定义的结果函数,或者由于没有记忆而第一次调用它结果。

上述两种实现之间的区别在于如何计算新结果。

  • 首先,每当
    state.applications
    状态更新时,
    selectListOfApplicationIdAndApplicationCompany
    都可能会重新计算其值,因为
    state.applications
    是一个新参考,无论
    state.applications.dict
    是否不同。
  • 在第二个中,我们要记住选择
    state.applications.dict
    的结果,因此如果
    state.applications
    更新但
    dict
    没有更新,那么
    selectApplicationsDict
    将重新计算并看到其结果相同并停在那里,
     selectListOfApplicationIdAndApplicationCompany
    的输入不会改变,也不会重新计算公司名称和 ID 的派生数组值。
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.