new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Redux Toolkit · RTK Query · all subjects

createapi

91 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

createApi configuration parameters

createApi accepts a single configuration object with the following options: baseQuery (required), endpoints (required), extractRehydrationInfo (optional), tagTypes (optional), reducerPath (optional), serializeQueryArgs (optional), keepUnusedDataFor (optional, value in seconds), refetchOnMountOrArgChange (optional, boolean or number in seconds), refetchOnFocus (optional), refetchOnReconnect (optional).

Why one API slice per base URL

Automatic tag invalidation only works within a single API slice. If you have multiple API slices, automatic invalidation won't work across them. Additionally, every createApi call generates its own middleware, and each middleware added to the store will run checks against every dispatched action. This adds a performance cost that accumulates, so calling createApi 10 times and adding 10 separate API middleware to the store will be noticeably slower.

createApi is the core RTK Query function

createApi is the core of RTK Query's functionality. It allows you to define a set of endpoints that describe how to retrieve data from backend APIs and other async sources, including configuration of how to fetch and transform data. It generates an API slice structure that contains Redux logic and optionally React hooks that encapsulate the data fetching and caching process.

createApi example with Pokemon API

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' import type { Pokemon } from './types' export const pokemonApi = createApi({ reducerPath: 'pokemonApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), endpoints: (build) => ({ getPokemonByName: build.query<Pokemon, string>({ query: (name) => `pokemon/${name}`, }), }), }) export const { useGetPokemonByNameQuery } = pokemonApi

serializeQueryArgs parameter

By default, serializeQueryArgs takes the query arguments, sorts object keys where applicable, stringifies the result, and concatenates it with the endpoint name. This creates a cache key based on the combination of arguments and endpoint name, ignoring object key order, so calling any endpoint with the same arguments results in the same cache key.

reducerPath parameter

reducerPath is an optional parameter for createApi that specifies the key under which the reducer will be mounted in the Redux store. If not provided, a default value is used.

API slice exports from createApi

createApi returns an API slice object with exports including: hooks (auto-generated based on endpoints, e.g., useGetPostsQuery, useAddPostMutation), endpoints (with initiate(), select(), and useQuery()/useMutation() methods), reducerPath, reducer, and middleware. The reducerPath, reducer, and middleware are used in store configuration, while endpoints provide access to the underlying endpoint implementations.

Hook feature comparison table

RTK Query hooks have overlapping features optimized for different situations. useQuery automatically triggers requests and subscribes to updates. useMutation allows manually triggering mutations. useQueryState returns state without triggering or subscribing. useQuerySubscription subscribes without returning full state. useLazyQuery allows manual triggering with subscription. useLazyQuerySubscription allows manual triggering without returning state. usePrefetch provides manual control without subscription. useQuery, useMutation, useLazyQuery, and useQuerySubscription support polling/refetching options. useQuery, useMutation, useLazyQuery, and useQueryState re-render as status and data become available. useQuery, useMutation, useLazyQuery, useQuerySubscription, and useLazyQuerySubscription subscribe component to keep cached data. useQuery, useMutation, useLazyQuery, and useQueryState return request status and cached data. useQuery and useQuerySubscription automatically trigger requests. useQuery, useLazyQuery, useQuerySubscription, and useLazyQuerySubscription accept polling/refetching options.

Generated hook naming convention

Generated React hooks follow the pattern use(Endpointname)(Query|Mutation|InfiniteQuery). For example, endpoints named getPosts and updatePost generate hooks named useGetPostsQuery, useLazyGetPostsQuery, useUpdatePostMutation, and api.useGetPostsQuery. The 'use' prefix is added, the first letter of the endpoint name is capitalized, and the hook type (Query, Mutation, or InfiniteQuery) is appended.

Implementation hooks vs primary hooks

Implementation hooks (useQueryState, useQuerySubscription, useLazyQuerySubscription, useInfiniteQueryState, useInfiniteQuerySubscription) exist as implementation details of primary hooks and may be useful in rare cases, but primary hooks should generally be used in applications.

Hooks available on endpoint definition and API object

Generated hooks are available in two ways: on the endpoint definition as generic names (e.g., api.endpoints.getPosts.useQuery) and on the api object with unique names (e.g., api.useGetPostsQuery). Endpoint-specific hooks with generic names on the endpoint object include useQuery, useMutation, useInfiniteQuery, useLazyQuery, useQueryState, useQuerySubscription, useLazyQuerySubscription, useInfiniteQueryState, and useInfiniteQuerySubscription. Endpoint-agnostic hooks on the api object include usePrefetch.

React hooks require @reduxjs/toolkit/query/react entry point

To auto-generate React hooks for RTK Query endpoints, you must import createApi from '@reduxjs/toolkit/query/react' rather than the base '@reduxjs/toolkit/query' package. The base package does not include React-specific functionality and is UI-agnostic.

createApi uses Redux Toolkit createSlice internally

Internally, createApi calls the Redux Toolkit createSlice API to generate a slice reducer and corresponding action creators with logic for caching fetched data. It also automatically generates a custom Redux middleware that manages subscription counts and cache lifetimes. Both the slice reducer and middleware must be added to your Redux store setup via configureStore.

createApi returns API slice object structure

When you call createApi, it automatically generates and returns an API service slice object containing Redux logic to interact with defined endpoints. This slice object includes a reducer to manage cached data, a middleware to manage cache lifetimes and subscriptions, and selectors and thunks for each endpoint. If imported from the React-specific entry point, it also includes auto-generated React hooks.

API slice structure fields

The generated API slice contains the following fields: reducerPath (string), reducer (Reducer), middleware (Middleware), endpoints (Record of endpoint definitions), injectEndpoints and enhanceEndpoints functions for code splitting, utils object with cache management functions, internalActions, and optionally generated React hooks if using React-specific createApi.

Single API slice per base URL best practice

You should typically have one API slice per base URL that your application communicates with. For example, if your site fetches from both /api/posts and /api/users, create a single API slice with /api/ as the base URL and separate endpoint definitions for posts and users. This allows you to effectively take advantage of automated re-fetching by defining tag relationships across endpoints.

Why single API slice: performance cost of multiple middleware

Each createApi call generates its own middleware. Every middleware added to the store runs checks against every dispatched action, which has a performance cost that adds up. Calling createApi 10 times and adding 10 separate API middleware to the store will be noticeably slower performance-wise.

React hooks import path

To use auto-generated React hooks for endpoints, import createApi from '@reduxjs/toolkit/query/react' instead of the base createApi. This provides a customized version that includes React hook functionality.

React hooks attached to endpoints

When using the React-specific createApi, generated React hooks are available on endpoint definitions as api.endpoints[endpointName].useQuery for queries and api.endpoints[endpointName].useMutation for mutations.

React hooks attached to API slice object

In addition to being attached to endpoint definitions, the same React hooks are also added directly to the API slice object with auto-generated names based on endpoint name and query/mutation type. For example, getPosts query hook becomes api.useGetPostsQuery() and updatePost mutation hook becomes api.useUpdatePostMutation().

Adding API middleware enables core RTK Query features

Adding the API middleware to the store enables caching, invalidation, polling, and other useful features of RTK Query.

reducer property contains the slice reducer function

The reducer property on the generated API object is a standard Redux slice reducer function containing the logic for updating the cached data. Add this to the Redux store using the reducerPath as the root state key.

Generated slice reducer and middleware must be added to Redux store

The generated slice reducer and the middleware both need to be added to your Redux store setup in configureStore in order for RTK Query to work correctly.

reducerPath property contains the reducerPath option

The reducerPath property on the generated API object contains the reducerPath option provided to createApi. Use this as the root state key when adding the reducer function to the store so that the rest of the generated API logic can find the state correctly.

createApi automatically calls createSlice internally

The createApi function internally calls the Redux Toolkit createSlice API to generate a slice reducer and corresponding action creators with the appropriate logic for caching fetched data.

createApi auto-generates a custom Redux middleware

createApi automatically generates a custom Redux middleware that manages subscription counts and cache lifetimes.

middleware property contains the custom Redux middleware

The middleware property on the generated API object is a custom Redux middleware that contains logic for managing caching, invalidation, subscriptions, polling, and more. Add this to the store setup after other middleware.

Example: configuring store with generated API slice and middleware

import { configureStore } from '@reduxjs/toolkit' import { setupListeners } from '@reduxjs/toolkit/query' import { pokemonApi } from './services/pokemon' export const store = configureStore({ reducer: { // Add the generated reducer as a specific top-level slice [pokemonApi.reducerPath]: pokemonApi.reducer, }, // Adding the api middleware enables caching, invalidation, polling, // and other useful features of `rtk-query`. middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(pokemonApi.middleware), }) // configure listeners using the provided defaults setupListeners(store.dispatch) This example shows how to add the generated API reducer and middleware to a Redux store and configure listeners.

RTK Query bundle size with RTK already installed

RTK Query adds approximately 9kb min+gzip to bundle size if Redux Toolkit is already being used, plus approximately 2kb for the hooks.

RTK Query bundle size without RTK installed

RTK Query adds approximately 17kb min+gzip without React or 19kb min+gzip with React (plus React-Redux as a peer dependency) when Redux Toolkit is not already installed.

RTK Query defines hooks in one central place

With RTK Query, hooks are defined in one central location by defining an API slice with multiple endpoints ahead of time, unlike React Query and SWR where hooks are defined on the fly across the codebase.

RTK Query dispatches normal Redux actions during requests

RTK Query dispatches normal Redux actions as requests are processed, making all actions visible in Redux DevTools and allowing Redux reducers to easily update global application state based on request lifecycle.

RTK Query main reasons to use

Main reasons to use RTK Query are: existing Redux app with desire to simplify data fetching; need to use Redux DevTools to see state change history; desire to integrate with Redux ecosystem; app logic needs to work outside of React.

RTK Query UI-agnostic functionality

Like Redux itself, the main RTK Query functionality is UI-agnostic and can be used with any UI layer, and everywhere Redux works.

RTK Query supported protocols

RTK Query supports any protocol with REST included by default.

buildThunks generates core thunks

The buildThunks method generates several thunks for the core module to use: queryThunk, mutationThunk, patchedQueryData, updateQueryData, upsertQueryData, prefetch, and buildMatchThunkActions. RTK-Query uses the same asyncThunk exposed from RTK.

buildMiddleware creates custom handlers

RTK-Query establishes a series of custom middlewares (referred to internally as handlers) to handle additional responses: buildDevCheckHandler, buildCacheCollectionHandler, buildInvalidationByTagsHandler, buildPollingHandler, buildCacheLifecycleHandler, and buildQueryLifecycleHandler.

buildSelectors exposes selector functions

The buildSelectors step exposes selector functions to the api and utils: buildQuerySelector, buildMutationSelector, selectInvalidatedBy, and selectCachedArgsForQuery.

Core module internal architecture

The core module takes the api and options passed to createApi() and calls an internal set of build methods. Each build method creates functions that are assigned to either api.util or api.internalActions and/or passed to a future build step.

createApi entry point and module system

When createApi() is called, it takes the provided options and calls the buildCreateApi() function internally, passing two modules: coreModule() which handles the majority of internal logic using core Redux functionality like slices and reducers, and reactHooksModule() which generates React hooks from endpoints using react-redux.

Modules customize endpoint handling

Modules are RTK-Query's method of customizing how the createApi method handles endpoints.

buildSlice creates internal slices

RTK-Query uses a Redux-centric architecture where the api is a slice of the store with its own slices created within it. The slices built include: querySlice, mutationSlice, invalidationSlice, subscriptionSlice (used as a dummy slice to generate actions internally), internalSubscriptionsSlice, and configSlice (for tracking focus state, online state, and hydration). buildSlice also exposes the core action resetApiState which is added to api.util.

RTK Query entry points

RTK Query is available via two entry points: 'import { createApi } from "@reduxjs/toolkit/query"' for the core API, and 'import { createApi } from "@reduxjs/toolkit/query/react"' for the React-specific entry point that automatically generates hooks corresponding to the defined endpoints.

RTK Query purpose and design approach

RTK Query is a powerful data fetching and caching tool designed to simplify common cases for loading data in a web application, eliminating the need to hand-write data fetching and caching logic. It is an optional addon included in the Redux Toolkit package, built on top of Redux Toolkit's createSlice and createAsyncThunk APIs. RTK Query can be used with any UI layer because Redux Toolkit is UI-agnostic. API endpoints are defined ahead of time, and RTK Query can generate React hooks that encapsulate the entire data fetching process.

Problems RTK Query solves

RTK Query solves the following problems in web applications: tracking loading state to show UI spinners, avoiding duplicate requests for the same data, providing optimistic updates to make the UI feel faster, and managing cache lifetimes as the user interacts with the UI. It addresses the distinction that data fetching and caching is a different set of concerns than state management, requiring purpose-built tools rather than relying solely on a general state management library like Redux.

RTK Query inspiration and unique features

RTK Query takes inspiration from tools like Apollo Client, React Query, Urql, and SWR. Its unique features include: building on Redux Toolkit's createSlice and createAsyncThunk APIs, being UI-agnostic, defining API endpoints ahead of time with parameter generation and response transformation, generating React hooks that provide data and isLoading fields, supporting cache entry lifecycle options for streaming updates, having working examples of code generation from OpenAPI and GraphQL schemas, and being completely written in TypeScript with an excellent TypeScript usage experience.

RTK Query core APIs

RTK Query includes four main APIs: createApi() for defining endpoints that describe how to retrieve data from backend APIs with configuration for fetching and transforming data; fetchBaseQuery() as a small wrapper around fetch to simplify requests and recommended as the baseQuery for most users; <ApiProvider /> for use as a Provider when you do not already have a Redux store; and setupListeners() for enabling refetchOnMount and refetchOnReconnect behaviors.

RTK Query bundle size impact

RTK Query adds a fixed one-time amount to bundle size. Estimated min+gzip sizes are: ~9kb for RTK Query and ~2kb for hooks if RTK is already in use; without RTK already in use, 17 kB for RTK+dependencies+RTK Query (without React), or 19kB plus React-Redux (with React, which is a peer dependency). Adding additional endpoint definitions increases size based only on code inside endpoint definitions, typically just a few bytes.

Creating an API slice with createApi

To create an API slice, import createApi and fetchBaseQuery from '@reduxjs/toolkit/query/react', define the slice with a reducerPath, baseQuery using fetchBaseQuery with the base URL, and endpoints as a builder function that returns endpoint definitions. Example: const pokemonApi = createApi({ reducerPath: 'pokemonApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), endpoints: (build) => ({ getPokemonByName: build.query<Pokemon, string>({ query: (name) => `pokemon/${name}` }) }) })

Exporting hooks from API slice

Hooks are auto-generated based on the defined endpoints and are exported from the API slice. For an endpoint like getPokemonByName, the auto-generated hook is useGetPokemonByNameQuery. These hooks can be imported and used directly in functional components.

Configuring Redux store for RTK Query

The API slice contains an auto-generated Redux slice reducer and custom middleware that manages subscription lifetimes. Both must be added to the Redux store: add the reducer at [pokemonApi.reducerPath]: pokemonApi.reducer in the reducer object, and add the middleware with getDefaultMiddleware().concat(pokemonApi.middleware). This enables caching, invalidation, polling, and other RTK Query features.

setupListeners for refetch behaviors

setupListeners(store.dispatch) is optional but required for refetchOnFocus and refetchOnReconnect behaviors. It can take an optional callback as the second argument for customization.

Using query hooks in React components

Query hooks automatically fetch data on mount, refetch when parameters change, and provide {data, isFetching} values in the result. Components re-render as these values change. Example: const { data, error, isLoading } = useGetPokemonByNameQuery('bulbasaur'). Hooks are also accessible via pokemonApi.endpoints.getPokemonByName.useQuery('bulbasaur').

One API slice per base URL pattern

The recommended pattern for RTK Query usage is to use createApi once per app, with one API slice per base URL as a rule of thumb.

Example: using type predicates in mutation error handling

import { useState } from 'react' import { useSnackbar } from 'notistack' import { api } from './services/api' import { isFetchBaseQueryError, isErrorWithMessage } from './services/helpers' function AddPost() { const { enqueueSnackbar, closeSnackbar } = useSnackbar() const [name, setName] = useState('') const [addPost] = useAddPostMutation() async function handleAddPost() { try { await addPost(name).unwrap() setName('') } catch (err) { if (isFetchBaseQueryError(err)) { const errMsg = 'error' in err ? err.error : JSON.stringify(err.data) enqueueSnackbar(errMsg, { variant: 'error' }) } else if (isErrorWithMessage(err)) { enqueueSnackbar(err.message, { variant: 'error' }) } } } return ( <div> <input value={name} onChange={(e) => setName(e.target.value)} /> <button>Add post</button> </div> ) } This shows using type predicates to safely handle different error types in mutation error handling.

RTK Query supports TypeScript versions from last 2 years

RTK Query supports TypeScript versions that were released within the last 2 years. If you encounter type problems not described in the documentation, open an issue on the Redux Toolkit repository.

RTK Query requires TypeScript 4.1+ for auto-generated React hooks

To use auto-generated React hooks from RTK Query, you must use TypeScript 4.1 or later. For older versions, use api.endpoints.[endpointName].useQuery/useMutation to access hooks directly.

dispatch and getState typing in createApi

createApi is called before the Redux store is created, so it cannot directly know or use RootState and AppDispatch types. By default, dispatch is typed as ThunkDispatch and getState is typed as () => unknown. Cast getState as RootState when needed to break circular type inference: const state = getState() as RootState. You may also include an explicit return type for the function to break the circular cycle.

SerializedError type for thrown errors

export interface SerializedError { name?: string message?: string stack?: string code?: string } When an unexpected error is thrown by user code rather than a handled error from baseQuery, it is transformed into a SerializedError shape.

Error type returned from hooks with fetchBaseQuery

When using fetchBaseQuery, the error property returned from a hook has type FetchBaseQueryError | SerializedError | undefined. Access error properties only after narrowing type to either FetchBaseQueryError or SerializedError.

Give your agent this brain