Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] RTK Query: add getSliceState arg to createSlice() to avoid reducerPath as selector #2355

Closed
AlexeiDarmin opened this issue May 25, 2022 · 2 comments

Comments

@AlexeiDarmin
Copy link

Proposal:

Instead of relying on state[api.reducerPath] internally to retrieve the store state, the library could rely on a new argument passed to createSlice({ getSliceState: (state, reducerPath) => state.get(reducerPath), ... }) then internally use getSliceState(state, api.reducerPath) for state references.

Explanation:

Currently createSlice() requires that reducerPath be a string. This string is then used internally by the library to traverse the store to reach the reducer via JS syntax such as state[api.reducerPath]. This does not work if the wrapper store state is defined in a non-JS syntax such as an Immutable Map from the ImmutableJS library and throws errors from RTK Query.

One breaking case occurs in buildHooks.ts, the culprit is state[api.reducerPath] which is invalid syntax in a custom store structure:

      const subscriptionRemoved = useSelector(
        (state: RootState<Definitions, string, string>) =>
          !!queryCacheKey &&
          !!requestId &&
          !state[api.reducerPath].subscriptions[queryCacheKey]?.[requestId]
      )

Feature request is to expose a mechanism for the developer to provide a selector that will select the correct slice from the store.

This pattern already exists within RTK's createEntityAdapter whereby a custom selector can be defined by the developer upon instantialization to reach this part of the store state:

From the docs:

// custom selector of specific entities
const booksAdapter = createEntityAdapter<Book>({
  selectId: (book) => book.bookId,
})

// Custom selector of entry to store slice
const booksSelectors = booksAdapter.getSelectors<RootState>(
  (state) => state.books
)

// immutable versions
const booksAdapter = createEntityAdapter<Book>({
  selectId: (book) => book.get('bookId'),
})

const booksSelectors = booksAdapter.getSelectors<RootState>(
  (state) => state.get('books')
)

I believe RTK-Query should be opinionated about the contents of objects defined within itself, however there should be an escape hatch to allow the developer to dictate how to reach this slice in the larger store state.

This will help support gradual migrations of large code bases that cannot hop-off from an immutable root store definition, but would still like to use this library.

Thanks for your time, I think the library is awesome :)

@phryneas
Copy link
Member

phryneas commented May 25, 2022

I'm sorry, but it's a no on that one from me. Aside from immutable there should really not be a single use case forever, and immutable has been abandoned for a long time, while we have been recommending against it for a very long time as well.

If you find yourself with an immutable root reducer, you can still do something like

Object.defineProperty(state, "api", {
  get: state.get("api")
})
// or even just
state.api = state.get("api")

in the root reducer before returning the newly generated state. While it is hacky, that should work just fine.

@AlexeiDarmin
Copy link
Author

AlexeiDarmin commented May 25, 2022

Thanks for the quick reply! I wasn't aware of the workaround. It makes sense to not support this proposal if that hack exists. I'll give it a shot and be perfectly content with things as they are if it works.

Feel free to close the issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants