You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Redux-Saga场景下带参数Reselect选择器的实现正确性验证及调用优化问询

回答

Great question! Let's break this down step by step to clarify your options and confirm what's working correctly.

1. Can you directly call the parameterized selector in sagas?

Absolutely! Your proposed syntax yield select((state) => makeGetPerson(state, id)) is fully valid and recommended.

Your current makeGetPerson selector follows Reselect's official pattern for parameterized selectors, and it works identically whether used in useSelector (components) or the select saga effect. The select effect accepts any function that takes the Redux state as input, so passing an inline function that invokes your selector with the required id is perfectly acceptable.

This approach is better than your current saga code (fetching the full list then filtering manually) because:

  • It reuses the exact same selection logic everywhere, eliminating duplicate code
  • If you ever update getPersonsList or adjust the filtering logic, you only need to modify selectors.js once
  • It keeps your saga code cleaner and aligned with your component-side state selection patterns

2. Alternative approaches to reduce saga dependency on store state

I understand your preference to avoid yield select in sagas to keep middleware decoupled from store state. Here are a few practical options to consider:

Pass required data via action payloads

Instead of fetching data from the store in the saga, pass the needed data directly when dispatching the action that triggers the saga. For example:

// In your component
const person = useSelector(state => makeGetPerson(state, id));
dispatch(runPersonRelatedSaga(person));

// In your saga
function* personRelatedSaga(action) {
  const person = action.payload;
  // Use person directly - no need for yield select!
}

This way, the saga only depends on the action payload, not the store's internal state structure.

Use selector factory functions (optional variation)

While your current parameterized selector is correct, another common Reselect pattern is to create a factory function that returns a selector bound to a specific parameter:

// selectors.js
const makeGetPerson = (id) => createSelector(
  getPersonsList,
  (persons) => persons.find(person => person.id === id)
);

// Component usage
const getPerson = makeGetPerson(id);
const person = useSelector(getPerson);

// Saga usage
yield select(makeGetPerson(id));

This is functionally similar to your current setup but can feel cleaner if you have multiple parameters or want to reuse the bound selector multiple times in the same scope.

Limit saga responsibilities to side effects

Restructure your logic so sagas only handle side effects (like API calls, timers, or external integrations) and don't need to read store state at all. For example:

  • If your saga needs to fetch details for a person, pass the id directly in the action (instead of fetching the person from the store first)
  • The saga uses the id to make the API call, then dispatches an action with the result to update the store

This keeps sagas focused on their core purpose and eliminates the need for yield select entirely.

3. Quick validation of your current selector setup

Your existing selector implementation is correct! Using Reselect with Immer is totally compatible—Immer handles immutable state updates in reducers, while Reselect caches derived state based on changes to the input selectors. There's no conflict here, and your approach follows best practices for Redux state selection.


内容的提问来源于stack exchange,提问作者lucataglia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 01:22:40