API design debate: selectors
field in createSlice
#3387
Replies: 6 comments 16 replies
-
Just giving context on how i'm currently doing reusable slices and accompanying selectors. The current way I have them implemented (pre-alpha 5) feels extreme and messy. Defining a reusable set of selectors
Setting up the slice into application state
Example of reusable component in our monorepo "common" library that takes the selectors and actions
This is how we are currently doing reusable slices/selectors So if you added a "getSelectors" function to the output of createSlice function, I would
I see that API design is still up in the air. That being said, would my above assumption be correct assuming you decided to go the getSelectors() route? |
Beta Was this translation helpful? Give feedback.
-
We're getting close to having RTK 2.0 done (per the 2.0 milestone issues list). The major remaining items have to do with nailing down final API design on the new features we've added, like the callback syntax for Specifically here, we have open questions around the new There are cases when you want to create multiple unique instances of a selector. This is most commonly because Reselect selectors have a default cache size of 1, and using the same selector instance in different components with different arguments passed in will cause the memoization to repeatedly fail and recalculate a different result every time. Reselect does now have a Right now we've got two different PRs with different possible approaches (example selectors are kinda pointless and here just to illustrate the difference in syntax):
const sliceWithSelectors = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1
},
},
selectors: {
selectValue: (state) => state.value,
},
selectorFactories: {
selectMultiply: () =>
createSelector(
(state: { value: number }) => state.value,
(_: unknown, multiplier: number) => multiplier,
(value, multiplier) => value * multiplier
),
},
})
export const { makeSelectMultiply } = sliceWithSelectors.selectorFactories;
export const oneSelectMultiplyInstance = makeSelectMultiply();
const sliceWithSelectors = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1
},
},
selectors: {
selectValue: (state) => state.value,
selectMultiply: {
factory: () =>
createSelector(
(state: { value: number }) => state.value,
(_: unknown, multiplier: number) => multiplier,
(value, multiplier) => value * multiplier
)
}
},
})
// call .getSelectors() each time you need a new instance
export const oneSelectMultiplyInstance = sliceWithSelectors.getSelectors( (state) => state.counter ) TradeoffsFor definitions, I think #3836 is probably simpler to read and use. One On the other hand, with #3671 the usage to make new selectors is probably simpler: import { makeSelectItemsByCategory } from './categoriesSlice'
function CategoryList({ category }) {
// Create a new memoized selector, for each component instance, on mount
const selectItemsByCategory = useMemo(makeSelectItemsByCategory, [])
const itemsByCategory = useSelector(state =>
selectItemsByCategory(state, category)
)
} whereas with #3836 it's more like: import { categorySlice } from './categoriesSlice'
function CategoryList({ category }) {
// Create a new memoized selector, for each component instance, on mount
const selectItemsByCategory = useMemo(() => categorySlice.getSelectors(selectSlice).selectItemsByCategory, [])
const itemsByCategory = useSelector(state =>
selectItemsByCategory(state, category)
)
} So, outstanding questions:
|
Beta Was this translation helpful? Give feedback.
-
Hey I have some questions regarding |
Beta Was this translation helpful? Give feedback.
-
This is what it would look like: |
Beta Was this translation helpful? Give feedback.
-
I have actually used |
Beta Was this translation helpful? Give feedback.
-
FWIW, we're currently looking at punting this decision past RTK 2.0. We can release the current-in-beta |
Beta Was this translation helpful? Give feedback.
-
In #3382 , we added a
selectors
field inside ofcreateSlice
, with an associatedslice.getSelectors(selectState)
method. Currently, that field is pretty limited. Selectors inside of it assume they get the slicestate
as an arg, but right now we're not sure about the right way to allow memoizing selectors in that field.We had an internal discussion about potential
selectors
field API design and use cases earlier today, which I am pasting here for reference:So, the open questions are:
We'd appreciate feedback on potential API design and use cases here!
Beta Was this translation helpful? Give feedback.
All reactions