如何管理一个 selector 以 yield select 接受参数?

How to manage a selector that accepts arguments with yield select?

我有一个 React 应用程序,我在其中使用 Redux 和 Redux-Saga 以及 Reselect 作为选择器库(使用 Immer 来处理 Redux 状态的不变性)。我写这个问题是因为我想了解我处理带有参数的选择器的方法是否完全正确。

我个人更喜欢避免将 yield select 放入 sagas,因为我想保留中间件 not depend on the Store's state,但我有遗留代码,其中包含带有 yield select 的 sagas .

下面是我必须编写的代码,用于实现我的选择器并将他调用到组件和 saga 中。我从 Reselec doc.

获得了选择器实现
// selectors.js: Selector implementation
const makeGetPerson = createSelector(
  getPersonsList,
  (state, id) => id,
  (persons, id) => persons.find((person) => person.id === id)
);

// components.js: if I have to use the selector into a component
const person = useSelector((state) => makeGetPerson(state, id))


// saga.js: if I have to use the selector into a saga
const persons = yield select(getPersonsList)
const person = persons.find((person) => person.id === id)

目前,从 saga 开始,我必须使用 return 元素列表的选择器并手动过滤它们。有没有办法在 a saga 中做类似 yield select((state) => getPersonsList(state, id)) 的事情?我还缺少其他方法吗?

select 效果创建器在 selector 函数之后接受附加参数,然后将这些参数发送到 selector 本身,因此您可以这样做:

const person = yield select(makeGetPerson, id);

文档:https://redux-saga.js.org/docs/api/#selectselector-args

您还可以将 createSelectPersonById 设为 curry:

const createSelectPersonById = id => createSelector(
  getPersonsList,
  (persons) => persons.find((person) => person.id === id)
);
// components
const person = useSelector(createSelectPersonById(id))
//saga
const person = yield select(createSelectPersonById(id));

在select person by id 你只是returning状态而不是一个新对象但是如果你每次都return一个新对象你可以在你的组件,这样当不相关的动作被分派时你就不会得到不必要的重新渲染:

//selector returning new object every time it is executed
const createSelectPersonById = (id) =>
  createSelector(getPersonsList, (persons) => {
    const person = persons.find(
      (person) => person.id === id
    );
    //returning a new object reference every time
    return {
      ...person,
      fullName:formatFullName(person)
    }
  });
//in components
const selectPersonById = React.useMemo(
  ()=>createSelectPersonById(id),
  [id]//selector only re created when id changes
)
const person = useSelector(selectPersonById);
//in saga nothing changes, no need to memoize:
const person = yield select(createSelectPersonById(id));

有关我如何以及为何在 React 中进行参数化 select 或 curry 的更多信息,请参见 here