Reputation: 10544
createSelector
mentioned at https://github.com/reduxjs/reselect
createSelector
API, which generates memoized selector functions. createSelector accepts one or more "input" selectors, which extract values from arguments, and an "output" selector that receives the extracted values and should return a derived value. If the generated selector is called multiple times, the output will only be recalculated when the extracted values have changed.
createDraftSafeSelector
mentioned at https://redux-toolkit.js.org/api/createSelector
createDraftSafeSelector
allows to create selectors that can safely be used inside ofcreateReducer
andcreateSlice
reducers with Immer-powered mutable logic. When used with plain state values, the selector will still memoize normally based on the inputs. But, when used with Immer draft values, the selector will err on the side of recalculating the results, just to be safe.
I am new to react and redux design patterns so could not understand the difference and purpose of createDraftSafeSelector
.
What is the difference in both API? What can be an example to understand the difference?
Upvotes: 3
Views: 4515
Reputation: 102237
See the real-world usage of the draft safe selector, interactionsBucketsSelectors.selectById(state.interactionsBuckets, convPk)
We can pass the draft state of immer.js in the draft safe selector in RTK case reducer.
The selectById
draft safe selector created in getSelectors().
createDraftSafeSelector
is a wrapper for createSelector
, it not only supports the general JS object state that createSelector
can handle, but also supports the draft State of immerjs, see source code:
import { current, isDraft } from 'immer'
import { createSelector } from 'reselect'
/**
* "Draft-Safe" version of `reselect`'s `createSelector`:
* If an `immer`-drafted object is passed into the resulting selector's first argument,
* the selector will act on the current draft value, instead of returning a cached value
* that might be possibly outdated if the draft has been modified since.
* @public
*/
export const createDraftSafeSelector: typeof createSelector = (
...args: unknown[]
) => {
const selector = (createSelector as any)(...args)
const wrappedSelector = (value: unknown, ...rest: unknown[]) =>
selector(isDraft(value) ? current(value) : value, ...rest)
return wrappedSelector as any
}
You may also want to see these two test cases about the difference between createSelector
and createDraftSafeSelector
.
If you don't pass the draft state of immerjs to selectors, you don't need to use createDraftSafeSelector
.
Upvotes: 0
Reputation: 44086
A selector created with createDraftSafeSelector
can be used safely within createReducer
or createSlice
reducers, which is not possible with createSelector
, as that one solely relies on object reference equality.
A selector created with createSelector
would always return the same result for one reducer call even if you modified the state in-between.
Most people never use selectors in reducers, so you will probably never need it.
Upvotes: 5