Reputation: 1819
I am trying to convert my Redux reducers, store etc using Thunks to use Redux-Toolkit (RTK) Query. Currently I have quite many thunks that are accessing the store to get some additional data before doing any queries to backend like this:
const someThunkCreator = (params: Params): AppThunk =>
async (dispatch, getState) => {
const someData = getState().some.nested.path.to.data
const moreData = getState().another.nested.path.to.data
// Probably do something with the data before querying
const response = await fetch(`${url}/${someData.id}`, {
method: 'PATCH',
body: {
...moreData,
...params
}
})
}
Now how should I convert that to RTK-Query endpoint? If I have multiple endpoints that are accessing some data in the store i.e. some user data, do I need to pass that data in as query parameter or is there some way to always inject that data into some specific queries? I guess with some enhancer I could inject that into every query, but then not all queries might need that data.
const myApi = createApi({
reducerPath: 'myApi',
baseQuery: fetchBaseQuery(),
endpoints: builder => ({
// Is there a way to do it this way?
updateSomething1: builder.mutation({
query: (something: TypeForSomething) => ({
url: `${userManagementUrl}/${userId}`, // Here the userId would be got from the store based on whoever is the current user using the app
method: 'PATCH',
something
})
}),
// Or do I need to do it this way and always somewhere in the code first get the data through some other endpoint query?
updateSomething2: builder.mutation({
query: (userId: string, something: TypeForSomething) => ({
url: `${userManagementUrl}/${userId}`,
method: 'PATCH',
something
})
}),
})
});
Upvotes: 2
Views: 2049
Reputation: 203198
Instead of using the query
function which only consumes a query argument
export type query = <QueryArg>( arg: QueryArg ) => string | Record<string, unknown>
use the queryFn
which consumes the passed query argument in addition to the base query API, extra options, and base query function.
queryFn( arg: QueryArg, api: BaseQueryApi, extraOptions: BaseQueryExtraOptions<BaseQuery>, baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery> ): MaybePromise< | { error: BaseQueryError<BaseQuery> data?: undefined } | { error?: undefined data: ResultType } >
The BaseQueryApi
has the function to access the store's state:
export interface BaseQueryApi { signal: AbortSignal dispatch: ThunkDispatch<any, any, any> getState: () => unknown }
Update the mutation endpoint to access the store from the api
argument and access the value(s) you need from state.
Example:
updateSomething1: builder.mutation</* ResultType */, TypeForSomething>({
queryFn: (something, api, extraOptions, baseQuery) => {
const state = api.getState() as RootState;
const userId = state.some.nested.path.to.data;
// or const userId = selectUserId(state); if you've selector functions
return baseQuery({
url: `${userManagementUrl}/${userId}`,
method: 'PATCH',
something
}) as { data: /* ResultType */ };
},
}),
/* ResultType */
is what you'll need to declare and provide for what you are actually returning.
Upvotes: 2