new·Earn with mozg — 20% of every monthSend somebody here and take a fifth of every plan payment they make, for as long as they keep paying — not a bounty on the first invoice. Your handle is the link, the window is thirty days, and the commission lands on your balance the second they pay. Free to join: if you have signed in, you already have the link. mozg.sh/earnall news →
mozg.beta
Sign in

Redux Toolkit · RTK Query · all subjects

api definition & hooks

28 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Endpoint structure fields and their types

Each endpoint in an API slice contains the following fields: initiate (InitiateRequestThunk), select (CreateCacheSelectorFactory), matchPending (Matcher<PendingAction>), matchFulfilled (Matcher<FulfilledAction>), and matchRejected (Matcher<RejectedAction>). These fields provide thunks, selectors, and action matchers for triggering data fetches and reading cached data.

initiate thunk signature for queries

For query endpoints, initiate has signature: (arg: any, options?: StartQueryActionCreatorOptions) => ThunkAction<QueryActionCreatorResult, any, any, UnknownAction>. The options parameter accepts subscribe (boolean), forceRefetch (boolean | number), and subscriptionOptions (which includes pollingInterval, refetchOnReconnect, and refetchOnFocus).

initiate thunk signature for mutations

For mutation endpoints, initiate has signature: (arg: any, options?: StartMutationActionCreatorOptions) => ThunkAction<MutationActionCreatorResult<D>, any, any, UnknownAction>. The options parameter accepts track (boolean, defaults to true), which controls whether the mutation is tracked in the store.

StartQueryActionCreatorOptions interface

StartQueryActionCreatorOptions contains: subscribe (optional boolean), forceRefetch (optional boolean | number), and subscriptionOptions (optional SubscriptionOptions). The forceRefetch option when set to true or a number will force a refetch even if data is cached.

initiate action returns unsubscribe callback

When dispatching an initiate action, the returned promise includes an unsubscribe callback. This callback should be called in the useEffect cleanup step to manually unsubscribe when a component unmounts. The pattern is: const result = dispatch(api.endpoints.getPost.initiate(postId)); return result.unsubscribe;

initiate query action creator example

Example of manually dispatching initiate for a query: const result = dispatch(api.endpoints.getPost.initiate(postId)); return result.unsubscribe; This subscribes to the query and returns an unsubscribe callback for cleanup.

Matchers for endpoint actions

Each endpoint provides three Redux Toolkit action matching utilities: matchPending, matchFulfilled, and matchRejected. These allow matching on pending, fulfilled, and rejected actions dispatched by the thunk, for use in createSlice.extraReducers or custom middleware. They are implemented as isAllOf(actionMatcher, matchesEndpoint(endpoint)).

Generated React hooks from query endpoints

Hooks are automatically generated based on the name of the endpoint in the service definition. An endpoint field with getPost: build.query() will generate a hook named useGetPostQuery, as well as a generically-named hook attached to the endpoint, like api.endpoints.getPost.useQuery.

Five query-related React hooks

RTK Query provides five query-related hooks: (1) useQuery - composes useQuerySubscription and useQueryState, automatically triggers fetches and subscribes the component to cached data; (2) useQuerySubscription - returns a refetch function, automatically triggers fetches and subscribes to cached data; (3) useQueryState - returns query state, accepts skip and selectFromResult, reads request status and cached data; (4) useLazyQuery - returns a tuple with trigger function, query result, and last promise info, with manual control over when fetching occurs, and trigger accepts preferCacheValue parameter; (5) useLazyQuerySubscription - returns a tuple with trigger function and last promise info, with manual control over when fetching occurs, and trigger accepts preferCacheValue parameter.

Query hook parameters

Query hooks expect two parameters: (queryArg?, queryOptions?). The queryArg param is passed through to the underlying query callback to generate the URL. The queryOptions object accepts additional parameters to control data fetching behavior.

Query hook options: skip

The skip query hook option allows a query to skip running for that render. It defaults to false.

Query hook options: selectFromResult

The selectFromResult query hook option allows altering the returned value of the hook to obtain a subset of the result, render-optimized for the returned subset.

Query hook return value: data

The data property on the query hook return object contains the latest returned result regardless of hook arg, if present.

Query hook return value: currentData

The currentData property on the query hook return object contains the latest returned result for the current hook arg, if present. It allows for granularity in showing only data corresponding to the current arg.

Query hook return value: error

The error property on the query hook return object contains the error result if present.

Query hook return value: isUninitialized

The isUninitialized property on the query hook return object, when true, indicates that the query has not started yet.

Query hook return value: isLoading

The isLoading property on the query hook return object, when true, indicates that the query is currently loading for the first time, and has no data yet. This is true for the first request fired off, but not for subsequent requests. isLoading refers to a query being in flight for the first time for the given hook, and no data will be available at this time.

Query hook return value: isFetching

The isFetching property on the query hook return object, when true, indicates that the query is currently fetching, but might have data from an earlier request. This is true for both the first request fired off, as well as subsequent requests. isFetching refers to a query being in flight for the given endpoint + query param combination, but not necessarily for the first time. Data may be available from an earlier request.

Query hook return value: isSuccess

The isSuccess property on the query hook return object, when true, indicates that the query has data from a successful request.

Query hook return value: isError

The isError property on the query hook return object, when true, indicates that the query is in an error state.

Query hook return value: refetch

The refetch property on the query hook return object is a function to force refetch the query.

selectFromResult performance optimization

selectFromResult allows you to get a specific segment from a query result in a performant manner. When using this feature, the component will not rerender unless the underlying data of the selected item has changed. If the selected item is one element in a larger collection, it will disregard changes to elements in the same collection. A shallow equality check is performed on the overall return value of selectFromResult to determine whether to force a rerender.

selectFromResult memoization requirement

When using selectFromResult, returned values must be correctly memoized. When intentionally providing an empty array or object to avoid re-creating it each time the callback runs, declare the empty array or object outside of the component to maintain a stable reference.

Example: Query hook with options

```tsx export const PostDetail = ({ id }: { id: string }) => { const { data: post, isFetching, isLoading, } = useGetPostQuery(id, { pollingInterval: 3000, refetchOnMountOrArgChange: true, skip: false, }) if (isLoading) return <div>Loading...</div> if (!post) return <div>Missing post!</div> return ( <div> {post.name} {isFetching ? '...refetching' : ''} </div> ) } ``` This example shows a PostDetail component that polls for updates every 3 seconds, refetches on mount or when the arg changes, and is not skipped.

Example: selectFromResult for extracting single item

```tsx function PostById({ id }: { id: number }) { const { post } = api.useGetPostsQuery(undefined, { selectFromResult: ({ data }) => ({ post: data?.find((post) => post.id === id), }), }) return <li>{post?.name}</li> } ``` This example shows using selectFromResult to extract a single post from a list, and the component will only rerender if that specific post's data changes.

Example: selectFromResult with stable empty array

```tsx const emptyArray: Post[] = [] function PostsList() { const { posts } = api.useGetPostsQuery(undefined, { selectFromResult: ({ data }) => ({ posts: data ?? emptyArray, }), }) return ( <ul> {posts.map((post) => ( <PostById key={post.id} id={post.id} /> ))} </ul> ) } ``` This example shows using a stable empty array declared outside the component to maintain a stable reference and avoid performance issues from re-creating the empty array each render.

Example: Managing UI with isLoading vs isFetching

```tsx import { Skeleton } from './Skeleton' import { useGetPostsQuery } from './api' function App() { const { data = [], isLoading, isFetching, isError } = useGetPostsQuery() if (isError) return <div>An error has occurred!</div> if (isLoading) return <Skeleton /> return ( <div className={isFetching ? 'posts--disabled' : ''}> {data.map((post) => ( <Post key={post.id} id={post.id} name={post.name} disabled={isFetching} /> ))} </div> ) } ``` This example shows using isLoading to display a skeleton while loading for the first time, and using isFetching to grey out data when changing pages or when data is invalidated and re-fetched.

Example: Managing UI with currentData

```tsx import { Skeleton } from './Skeleton' import { useGetPostsByUserQuery } from './api' function PostsList({ userName }: { userName: string }) { const { currentData, isFetching, isError } = useGetPostsByUserQuery(userName) if (isError) return <div>An error has occurred!</div> if (isFetching && !currentData) return <Skeleton /> return ( <div className={isFetching ? 'posts--disabled' : ''}> {currentData ? currentData.map((post) => ( <Post key={post.id} id={post.id} name={post.name} disabled={isFetching} /> )) : 'No data available'} </div> ) } ``` This example shows using currentData to only show data for the current arg. If posts are being fetched for the first time, a skeleton is shown. If posts for the current user have previously been fetched and are re-fetching, the UI shows the previous data but greyed out. If the user changes, the skeleton is shown again instead of greying out data for the previous user.

Give your agent this brain