### configureStore Full Setup Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/configureStore.mdx A comprehensive example demonstrating how to configure a Redux store with reducers, middleware, preloaded state, and custom enhancers. ```APIDOC ## configureStore Full Example ### Description Demonstrates the full capabilities of `configureStore`, including slice reducers, custom middleware, devTools toggling, preloaded state, and custom enhancers. ### Request Example ```ts const store = configureStore({ reducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger), devTools: process.env.NODE_ENV !== 'production', preloadedState, enhancers: (getDefaultEnhancers) => getDefaultEnhancers({ autoBatch: false }).concat(batchedSubscribe(debounceNotify)), }) ``` ``` -------------------------------- ### Organize Listeners with Setup Function Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/createListenerMiddleware.mdx Create a setup function within the slice file that accepts a `startListening` function. The listener file then calls this setup function on startup. ```typescript import type { AppStartListening } from '../../app/listenerMiddleware' const feature1Slice = createSlice(/* */) const { action1 } = feature1Slice.actions export default feature1Slice.reducer export const addFeature1Listeners = (startListening: AppStartListening) => { startListening({ actionCreator: action1, effect: () => {}, }) } ``` ```typescript import { addFeature1Listeners } from '../features/feature1/feature1Slice' addFeature1Listeners(listenerMiddleware.startListening) ``` -------------------------------- ### Setup: Replacing createStore with configureStore Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/skills/evolve-and-diagnose-redux-apps/migrate-to-modern-redux/SKILL.md Demonstrates how to replace the legacy `createStore` setup with Redux Toolkit's `configureStore`. ```APIDOC ## Setup: Replacing createStore with configureStore ### Description This section shows the transformation from a legacy Redux store setup using `createStore` and `applyMiddleware` to the modern approach with `configureStore` from Redux Toolkit. ### Method N/A (Code Example) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A #### Success Response (200) N/A #### Response Example ```ts // before import { applyMiddleware, combineReducers, createStore } from 'redux' import thunk from 'redux-thunk' const postsReducer = (state = [] as { id: string; title: string }[]) => state const usersReducer = (state = [] as { id: string; name: string }[]) => state const rootReducer = combineReducers({ posts: postsReducer, users: usersReducer, }) export const legacyStore = createStore(rootReducer, applyMiddleware(thunk)) // after import { configureStore } from '@reduxjs/toolkit' const postsReducer = (state = [] as { id: string; title: string }[]) => state const usersReducer = (state = [] as { id: string; name: string }[]) => state export const store = configureStore({ reducer: { posts: postsReducer, users: usersReducer, }, }) ``` ``` -------------------------------- ### Advanced Store Setup with Middleware and Enhancers Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/configureStore.mdx A comprehensive example demonstrating custom middleware, preloaded state, and advanced enhancer configuration using getDefaultEnhancers. ```typescript const store = configureStore({ reducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger), devTools: process.env.NODE_ENV !== 'production', preloadedState, enhancers: (getDefaultEnhancers) => getDefaultEnhancers({ autoBatch: false, }).concat(batchedSubscribe(debounceNotify)), }) ``` -------------------------------- ### onQueryStarted Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/createApi.mdx An example demonstrating the usage of the `onQueryStarted` lifecycle function within a query endpoint, showing how to dispatch actions and handle query fulfillment. ```APIDOC ## `onQueryStarted` Example ### Description This example shows how to use the `onQueryStarted` lifecycle function in a query endpoint to dispatch actions before, on success, and on error of the query. ### Code ```ts // file: notificationsSlice.ts noEmit export const messageCreated = (msg: string) => ({ type: 'notifications/messageCreated', payload: msg, }) // file: api.ts import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' import { messageCreated } from './notificationsSlice' export interface Post { id: number name: string } const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/', }), endpoints: (build) => ({ getPost: build.query({ query: (id) => `post/${id}`, async onQueryStarted(id, { dispatch, queryFulfilled }) { // `onStart` side-effect dispatch(messageCreated('Fetching post...')) try { const { data } = await queryFulfilled // `onSuccess` side-effect dispatch(messageCreated('Post received!')) } catch (err) { // `onError` side-effect dispatch(messageCreated('Error fetching post!')) } }, }), }), }) ``` ``` -------------------------------- ### Basic Redux Toolkit Store Setup Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/usage/migrating-to-modern-redux.mdx Demonstrates the simplified store configuration using configureStore, which automatically handles reducer combination, middleware setup, and DevTools integration. ```javascript import { configureStore } from '@reduxjs/toolkit' import postsReducer from '../reducers/postsReducer' import usersReducer from '../reducers/usersReducer' const store = configureStore({ reducer: { posts: postsReducer, users: usersReducer, }, }) ``` -------------------------------- ### Redux Toolkit Setup and Basic Data Flow Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/skills/build-modern-redux-apps/redux-dataflow/SKILL.md Demonstrates the initial setup of a Redux store using Redux Toolkit, defining slices, actions, reducers, and selectors to manage application state and derived data. ```APIDOC ## Redux Toolkit Setup and Basic Data Flow ### Description This section shows how to set up a Redux store with Redux Toolkit, including creating slices, defining reducers and actions, and using `createSelector` to derive state. ### Method N/A (Configuration and Usage Example) ### Endpoint N/A ### Parameters N/A ### Request Example ```ts import { configureStore, createSelector, createSlice } from '@reduxjs/toolkit' const postsSlice = createSlice({ name: 'posts', initialState: { items: [] as { id: string; title: string; published: boolean }[], filter: 'all' as 'all' | 'published', }, reducers: { postAdded(state, action: { payload: { id: string; title: string } }) { state.items.push({ ...action.payload, published: false }) }, postPublished(state, action: { payload: { id: string } }) { const post = state.items.find((item) => item.id === action.payload.id) if (post) { post.published = true } }, filterChanged(state, action: { payload: 'all' | 'published' }) { state.filter = action.payload }, }, }) const store = configureStore({ reducer: { posts: postsSlice.reducer, }, }) type RootState = ReturnType const selectPostsState = (state: RootState) => state.posts const selectVisiblePosts = createSelector([selectPostsState], (postsState) => postsState.filter === 'all' ? postsState.items : postsState.items.filter((post) => post.published), ) store.dispatch(postsSlice.actions.postAdded({ id: 'p1', title: 'Draft' })) store.dispatch(postsSlice.actions.postPublished({ id: 'p1' })) const visiblePosts = selectVisiblePosts(store.getState()) console.log(visiblePosts) ``` ### Response N/A (This is a client-side setup and usage example) ### Response Example N/A ``` -------------------------------- ### Manual Redux Store Setup with Middleware and DevTools Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/usage/usage-guide.md Demonstrates a manual Redux store setup process using `createStore`, `applyMiddleware`, and `redux-devtools-extension`. It includes configuring logger and thunk middleware, applying enhancers, and enabling hot module replacement for reducers. This approach can be verbose and prone to errors due to argument order and global namespace checks for DevTools. ```javascript import { applyMiddleware, createStore } from 'redux' import { composeWithDevTools } from 'redux-devtools-extension' import thunkMiddleware from 'redux-thunk' import monitorReducersEnhancer from './enhancers/monitorReducers' import loggerMiddleware from './middleware/logger' import rootReducer from './reducers' export default function configureStore(preloadedState) { const middlewares = [loggerMiddleware, thunkMiddleware] const middlewareEnhancer = applyMiddleware(...middlewares) const enhancers = [middlewareEnhancer, monitorReducersEnhancer] const composedEnhancers = composeWithDevTools(...enhancers) const store = createStore(rootReducer, preloadedState, composedEnhancers) if (process.env.NODE_ENV !== 'production' && module.hot) { module.hot.accept('./reducers', () => store.replaceReducer(rootReducer)) } return store } ``` -------------------------------- ### Accessing usePrefetch Hook Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/created-api/hooks.mdx Shows a practical example of how to access and use the `usePrefetch` hook within a React component. It demonstrates calling the hook with an endpoint name and optional configuration to get a callback function that can be invoked to prefetch data. ```typescript const prefetchCallback = api.usePrefetch(endpointName, options) ``` -------------------------------- ### Install Dependencies Source: https://github.com/reduxjs/redux-toolkit/blob/master/website/README.md Installs all project dependencies required for development and building. This command uses the yarn package manager. ```bash yarn ``` -------------------------------- ### Basic Usage Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/createListenerMiddleware.mdx Demonstrates how to set up and use the `createListenerMiddleware` in a Redux store, including defining a listener that reacts to a specific action. ```javascript import { configureStore, createListenerMiddleware } from '@reduxjs/toolkit' import todosReducer, { todoAdded, todoToggled, todoDeleted, } from '../features/todos/todosSlice' // Create the middleware instance and methods const listenerMiddleware = createListenerMiddleware() // Add one or more listener entries that look for specific actions. // They may contain any sync or async logic, similar to thunks. listenerMiddleware.startListening({ actionCreator: todoAdded, effect: async (action, listenerApi) => { // Run whatever additional side-effect-y logic you want here console.log('Todo added: ', action.payload.text) // Can cancel other running instances listenerApi.cancelActiveListeners() // Run async logic const data = await fetchData() // Pause until action dispatched or state changed if (await listenerApi.condition(matchSomeAction)) { // Use the listener API methods to dispatch, get state, // unsubscribe the listener, start child tasks, and more listenerApi.dispatch(todoAdded('Buy pet food')) // Spawn "child tasks" that can do more work and return results const task = listenerApi.fork(async (forkApi) => { // Can pause execution await forkApi.delay(5) // Complete the child by returning a value return 42 }) const result = await task.result // Unwrap the child result in the listener if (result.status === 'ok') { // Logs the `42` result value that was returned console.log('Child succeeded: ', result.value) } } }, }) const store = configureStore({ reducer: { todos: todosReducer, }, // Add the listener middleware to the store. // NOTE: Since this can receive actions with functions inside, // it should go before the serializability check middleware middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(listenerMiddleware.middleware), }) ``` -------------------------------- ### Basic Usage of autoBatchEnhancer with createSlice Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/autoBatchEnhancer.mdx Demonstrates how to use `autoBatchEnhancer` and `prepareAutoBatched` with `createSlice` to dispatch batched, low-priority actions. This example shows the setup for a counter slice where increments are batched and decrements are not. ```typescript import { createSlice, configureStore, autoBatchEnhancer, prepareAutoBatched, } from '@reduxjs/toolkit' interface CounterState { value: number } const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 } satisfies CounterState as CounterState, reducers: { incrementBatched: { // Batched, low-priority reducer(state) { state.value += 1 }, // highlight-start // Use the `prepareAutoBatched` utility to automatically // add the `action.meta[SHOULD_AUTOBATCH]` field the enhancer needs prepare: prepareAutoBatched(), // highlight-end }, // Not batched, normal priority decrementUnbatched(state) { state.value -= 1 }, }, }) const { incrementBatched, decrementUnbatched } = counterSlice.actions // includes batch enhancer by default, as of RTK 2.0 const store = configureStore({ reducer: counterSlice.reducer, }) ``` -------------------------------- ### RTK Query `onQueryStarted` Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/createApi.mdx Demonstrates how to use the `onQueryStarted` lifecycle method in an RTK Query endpoint. This example dispatches actions to show fetching status and handles success or error states. ```typescript // file: notificationsSlice.ts noEmit export const messageCreated = (msg: string) => ({ type: 'notifications/messageCreated', payload: msg, }) // file: api.ts import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' import { messageCreated } from './notificationsSlice' export interface Post { id: number name: string } const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/', }), endpoints: (build) => ({ getPost: build.query({ query: (id) => `post/${id}`, async onQueryStarted(id, { dispatch, queryFulfilled }) { // `onStart` side-effect dispatch(messageCreated('Fetching post...')) try { const { data } = await queryFulfilled // `onSuccess` side-effect dispatch(messageCreated('Post received!')) } catch (err) { // `onError` side-effect dispatch(messageCreated('Error fetching post!')) } }, }), }), }) ``` -------------------------------- ### Start Metro Server for React Native Source: https://github.com/reduxjs/redux-toolkit/blob/master/examples/publish-ci/react-native/README.md Starts the Metro bundler, which is essential for running React Native applications. This command should be executed from the root of your project. ```bash # using npm npm start # OR using Yarn yarn start ``` -------------------------------- ### Setup RTK Query API, Store, and React Component Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/skills/manage-server-data/adopt-rtk-query/SKILL.md Demonstrates the complete setup for RTK Query, including defining the API slice with createApi, integrating it into the Redux store using configureStore, and consuming the generated hooks in a React component. ```tsx // file: src/services/api.ts import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' type Post = { id: string; title: string } export const api = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: '/api/' }), tagTypes: ['Post'], endpoints: (build) => ({ getPosts: build.query({ query: () => 'posts', providesTags: (result) => result ? [...result.map(({ id }) => ({ type: 'Post' as const, id })), 'Post'] : ['Post'], }), addPost: build.mutation>({ query: (body) => ({ url: 'posts', method: 'POST', body, }), invalidatesTags: ['Post'], }), }), }) export const { useGetPostsQuery, useAddPostMutation } = api // file: src/app/store.ts import { configureStore } from '@reduxjs/toolkit' import { api } from '../services/api' export const store = configureStore({ reducer: { [api.reducerPath]: api.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware), }) // file: src/App.tsx import { Provider } from 'react-redux' import { store } from './app/store' import { useAddPostMutation, useGetPostsQuery } from './services/api' function Posts() { const { data: posts = [] } = useGetPostsQuery() const [addPost] = useAddPostMutation() return (
    {posts.map((post) => (
  • {post.title}
  • ))}
) } export function App() { return ( ) } ``` -------------------------------- ### Installing Dependencies for RTK Codemods Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/rtk-codemods/README.md These commands outline the steps to set up the development environment for RTK Codemods. It involves cloning the repository, changing the directory, and installing project dependencies using yarn. ```bash git clone cd reduxjs/redux-toolkit yarn ``` -------------------------------- ### Start Local Development Server Source: https://github.com/reduxjs/redux-toolkit/blob/master/website/README.md Launches the local development server with hot-reloading enabled. Changes to the source files are reflected in the browser automatically. ```bash yarn start ``` -------------------------------- ### startListening Method Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/createListenerMiddleware.mdx Adds a new listener entry to the middleware, typically used to statically add new listeners during application setup. ```APIDOC ### `startListening` Adds a new listener entry to the middleware. Typically used to "statically" add new listeners during application setup. ```ts const startListening = (options: AddListenerOptions) => UnsubscribeListener interface AddListenerOptions { // Four options for deciding when the listener will run: // 1) Exact action type string match type?: string // 2) Exact action type match based on the RTK action creator actionCreator?: ActionCreator // 3) Match one of many actions using an RTK matcher matcher?: Matcher // 4) Return true based on a combination of action + state predicate?: ListenerPredicate // The actual callback to run when the action is matched effect: (action: Action, listenerApi: ListenerApi) => void | Promise } type ListenerPredicate = ( action: Action, currentState?: State, originalState?: State, ) => boolean type UnsubscribeListener = ( unsubscribeOptions?: UnsubscribeListenerOptions, ) => void interface UnsubscribeListenerOptions { cancelActive?: true } ``` **You must provide exactly _one_ of the four options for deciding when the listener will run: `type`, `actionCreator`, `matcher`, or `predicate`**. Every time an action is dispatched, each listener will be checked to see if it should run based on the current action vs the comparison option provided. These are all acceptable: ```js // 1) Action type string listenerMiddleware.startListening({ type: 'todos/todoAdded', effect }) // 2) RTK action creator listenerMiddleware.startListening({ actionCreator: todoAdded, effect }) // 3) RTK matcher function listenerMiddleware.startListening({ matcher: isAnyOf(todoAdded, todoToggled), effect, }) // 4) Listener predicate listenerMiddleware.startListening({ predicate: (action, currentState, previousState) => { // return true when the listener should run }, effect, }) ``` Note that the `predicate` option actually allows matching solely against state-related checks, such as "did `state.x` change" or "the current value of `state.x` matches some criteria", regardless of the actual action. The ["matcher" utility functions included in RTK](./matching-utilities.mdx) are acceptable as either the `matcher` or `predicate` option. The return value is an `unsubscribe()` callback that will remove this listener. By default, unsubscribing will _not_ cancel any active instances of the listener. However, you may also pass in `{cancelActive: true}` to cancel running instances. If you try to add a listener entry but another entry with this exact function reference already exists, no new entry will be added, and the existing `unsubscribe` method will be returned. The `effect` callback will receive the current action as its first argument, as well as a "listener API" object similar to the "thunk API" object in `createAsyncThunk`. All listener predicates and callbacks are checked _after_ the root reducer has already processed the action and updated the state. The `listenerApi.getOriginalState()` method can be used to get the state value that existed before the action that triggered this listener was processed. ``` -------------------------------- ### API Endpoint Usage Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/createApi.mdx Demonstrates how to define query and mutation endpoints within `createApi` and how the generated hooks are used. ```APIDOC ## API Endpoint Usage ### Description When defining an endpoint like `getPosts`, this name becomes exportable and can be referenced via hooks like `useGetPostsQuery()`, `api.endpoints.getPosts.initiate()`, and `api.endpoints.getPosts.select()`. The same applies to mutations, which use `useMutation`. ### Example ```typescript import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' interface Post { id: number name: string } type PostsResponse = Post[] const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/' }), tagTypes: ['Posts'], endpoints: (build) => ({ getPosts: build.query({ query: () => 'posts', providesTags: (result) => result ? result.map(({ id }) => ({ type: 'Posts', id })) : [], }), addPost: build.mutation>({ query: (body) => ({ url: `posts`, method: 'POST', body, }), invalidatesTags: ['Posts'], }), }), }) // Auto-generated hooks export const { useGetPostsQuery, useAddPostMutation } = api // Possible exports export const { endpoints, reducerPath, reducer, middleware } = api // reducerPath, reducer, middleware are only used in store configuration // endpoints will have: // endpoints.getPosts.initiate(), endpoints.getPosts.select(), endpoints.getPosts.useQuery() // endpoints.addPost.initiate(), endpoints.addPost.select(), endpoints.addPost.useMutation() // see `createApi` overview for _all exports_ ``` ``` -------------------------------- ### Setup Endpoint for Pagination Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/usage/pagination.mdx Defines a paginated endpoint that accepts a page argument and returns a list of posts. ```APIDOC ## POST /posts ### Description Sets up an endpoint to fetch a paginated list of posts. The `page` argument determines which page of results to retrieve. ### Method GET ### Endpoint `/posts?page=` ### Parameters #### Query Parameters - **page** (number) - Optional - The page number to retrieve. Defaults to 1. ### Request Example ```json { "example": "/posts?page=1" } ``` ### Response #### Success Response (200) - **page** (number) - The current page number. - **per_page** (number) - The number of items per page. - **total** (number) - The total number of items available. - **total_pages** (number) - The total number of pages. - **data** (array) - An array of post objects. #### Response Example ```json { "page": 1, "per_page": 10, "total": 100, "total_pages": 10, "data": [ { "id": 1, "name": "Post 1" } ] } ``` ``` -------------------------------- ### Starting a Listener with RTK Matcher Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/createListenerMiddleware.mdx Use `startListening` with the `matcher` option to trigger a listener when an action matches any of the provided RTK matcher functions. ```javascript listenerMiddleware.startListening({ matcher: isAnyOf(todoAdded, todoToggled), effect, }) ``` -------------------------------- ### Customize Redux Store with Middleware and Enhancers Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/usage/usage-guide.md Provides an example of a customized store setup including preloaded state, custom middleware, enhancers, and hot reloading support. ```javascript import { configureStore } from '@reduxjs/toolkit' import monitorReducersEnhancer from './enhancers/monitorReducers' import loggerMiddleware from './middleware/logger' import rootReducer from './reducers' export default function configureAppStore(preloadedState) { const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(loggerMiddleware), preloadedState, enhancers: (getDefaultEnhancers) => getDefaultEnhancers().concat(monitorReducersEnhancer), }) if (process.env.NODE_ENV !== 'production' && module.hot) { module.hot.accept('./reducers', () => store.replaceReducer(rootReducer)) } return store } ``` -------------------------------- ### New Callback Syntax for createSlice with Thunks Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/usage/migrating-rtk-2.md This example demonstrates the new callback syntax for `createSlice` which allows defining async thunks directly within the slice. It requires a custom `createSlice` setup with `asyncThunkCreator`. ```typescript const createAppSlice = buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator }, }) const todosSlice = createAppSlice({ name: 'todos', initialState: { loading: false, todos: [], error: null, } as TodoState, reducers: (create) => ({ // A normal "case reducer", same as always deleteTodo: create.reducer((state, action: PayloadAction) => { state.todos.splice(action.payload, 1) }), // A case reducer with a "prepare callback" to customize the action addTodo: create.preparedReducer( (text: string) => { const id = nanoid() return { payload: { id, text } } }, // action type is inferred from prepare callback (state, action) => { state.todos.push(action.payload) }, ), // An async thunk fetchTodo: create.asyncThunk( // Async payload function as the first argument async (id: string, thunkApi) => { const res = await fetch(`myApi/todos?id=${id}`) return (await res.json()) as Item }, // An object containing `{pending?, rejected?, fulfilled?, settled?, options?}` second { pending: (state) => { state.loading = true }, rejected: (state, action) => { state.error = action.payload ?? action.error }, fulfilled: (state, action) => { state.todos.push(action.payload) } } ) }) }) ``` -------------------------------- ### setupListeners Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/etc/rtk-query-react.api.md Sets up automatic listeners for common browser events (like focus, online/offline) to re-fetch data when appropriate. ```APIDOC ## setupListeners ### Description Sets up automatic listeners for common browser events (like focus, online/offline) to re-fetch data when appropriate. This helps keep your application's data up-to-date. ### Method `setupListeners` ### Endpoint N/A (This is a function to be called during store setup) ### Parameters - **dispatch** (ThunkDispatch) - The Redux store's dispatch function. - **customHandler** (function) - Optional - A function to customize the event listeners and their actions. - This function receives `dispatch` and an object containing event handler functions (`onFocus`, `onFocusLost`, `onOnline`, `onOffline`). - It should return a function that cleans up the listeners when called. ### Request Example ```javascript import { setupListeners } from '@reduxjs/toolkit/query'; const store = configureStore({ reducer: rootReducer, }); setupListeners(store.dispatch); // With custom handler: setupListeners(store.dispatch, (dispatch, { onFocus }) => { const unsubscribe = onFocus(() => { console.log('Window focused, revalidating queries...'); // Custom logic here, e.g., revalidate specific queries }); return unsubscribe; // Cleanup function }); ``` ### Response Returns a function that can be called to unsubscribe all listeners. #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Redux Toolkit React Integration Guide Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/tutorials/quick-start.mdx A comprehensive guide on connecting Redux Toolkit state management to React components. ```APIDOC ## Redux Toolkit Integration ### Description This guide outlines the standard pattern for integrating Redux Toolkit into a React application, covering store configuration, provider wrapping, and component-level state interaction. ### Core Concepts - **configureStore**: Initializes the Redux store with default middleware and reducer configuration. - **createSlice**: Simplifies reducer and action creator generation using Immer for immutable updates. - **Provider**: A React-Redux component that makes the store available to all nested components. - **useSelector**: Hook to extract data from the Redux store state. - **useDispatch**: Hook to obtain the dispatch function for triggering state changes. ### Implementation Steps 1. **Store Setup**: Define your root store using `configureStore`. 2. **Provider Wrapping**: Wrap your root component with ``. 3. **Slice Creation**: Use `createSlice` to define state logic and export actions. 4. **Component Usage**: Use `useSelector` to read state and `useDispatch` to trigger actions. ### Example: Counter Slice ```ts import { createSlice } from '@reduxjs/toolkit' const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1 }, decrement: (state) => { state.value -= 1 }, }, }) export const { increment, decrement } = counterSlice.actions export default counterSlice.reducer ``` ### Example: React Component ```tsx import { useSelector, useDispatch } from 'react-redux' export function Counter() { const count = useSelector((state: RootState) => state.counter.value) const dispatch = useDispatch() return ( ) } ``` -------------------------------- ### Install Redux Toolkit for New Apps (Vite/Next.js) Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/README.md Commands to set up a new React project with Redux Toolkit pre-configured using Vite with a Redux+TS template or Next.js with the 'with-redux' template. ```bash npx degit reduxjs/redux-templates/packages/vite-template-redux my-app ``` ```bash npx create-next-app --example with-redux my-app ``` -------------------------------- ### setupListeners Function Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/etc/rtk-query.api.md Sets up listeners for various events (focus, online/offline) to trigger refetches or other actions. ```APIDOC ## setupListeners ### Description Sets up event listeners for focus, online, and offline events to manage data refetching and application state. ### Method Not applicable (this is a setup function). ### Endpoint Not applicable. ### Parameters - **dispatch** (ThunkDispatch) - Required - The Redux dispatch function. - **customHandler** (function) - Optional - A custom handler function to override default listener behavior. ### Request Example ```javascript import { setupListeners } from '@reduxjs/toolkit/query' const unsubscribe = setupListeners(dispatch) // To unsubscribe later: unsubscribe() ``` ### Response #### Success Response (200) Not applicable. #### Response Example Not applicable. ``` -------------------------------- ### Legacy Redux Store Setup Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/usage/migrating-to-modern-redux.mdx Shows the traditional approach to creating a Redux store, which involves manual reducer combination, middleware application, and DevTools composition. ```javascript import { createStore, applyMiddleware, combineReducers, compose } from 'redux' import thunk from 'redux-thunk' import postsReducer from '../reducers/postsReducer' import usersReducer from '../reducers/usersReducer' const rootReducer = combineReducers({ posts: postsReducer, users: usersReducer, }) const middlewareEnhancer = applyMiddleware(thunk) const composeWithDevTools = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose const composedEnhancers = composeWithDevTools(middlewareEnhancer) const store = createStore(rootReducer, composedEnhancers) ``` -------------------------------- ### Install Dependencies and Build Project Source: https://github.com/reduxjs/redux-toolkit/blob/master/CONTRIBUTING.md Commands to install project dependencies using Yarn and build the Redux Toolkit packages. These commands are essential for local development and testing. ```bash cd redux-toolkit yarn yarn build ``` -------------------------------- ### Setup Listeners for Refetching Behaviors Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/README.md The setupListeners utility is used to enable automatic refetching behaviors like refetchOnMount and refetchOnReconnect within RTK Query. It should be called after the store is configured and the API provider is set up. ```typescript import { setupListeners } from "@reduxjs/toolkit/query" import { pokemonApi } from "./pokemonApi" const store = configureStore({ reducer: { [pokemonApi.reducerPath]: pokemonApi.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(pokemonApi.middleware), }); setupListeners(store.dispatch); ``` -------------------------------- ### Install Redux Toolkit and React-Redux Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/tutorials/quick-start.mdx Installs the necessary packages for Redux Toolkit and React-Redux using npm. These packages are essential for managing application state with Redux in a React environment. ```sh npm install @reduxjs/toolkit react-redux ``` -------------------------------- ### useLazyQuerySubscription Hook Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/created-api/hooks.mdx Provides an example of using the `useLazyQuerySubscription` hook, which returns a `trigger` function and the `lastArg`. This hook is useful for initiating queries on demand rather than automatically on component mount. ```typescript const [trigger, lastArg] = api.endpoints.getPosts.useLazyQuerySubscription(options) ``` -------------------------------- ### Initialize New Redux Projects with Templates Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/introduction/getting-started.md Commands to scaffold a new React application pre-configured with Redux Toolkit using Vite or Next.js templates. ```bash # Vite with our Redux+TS template npx degit reduxjs/redux-templates/packages/vite-template-redux my-app # Next.js using the with-redux template npx create-next-app --example with-redux my-app ``` -------------------------------- ### RTK Query API Setup with Endpoints Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/createApi.mdx Demonstrates setting up a basic RTK Query API with query and mutation endpoints, including tag types and auto-generated hooks. ```typescript import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' interface Post { id: number name: string } type PostsResponse = Post[] const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/' }), tagTypes: ['Posts'], endpoints: (build) => ({ getPosts: build.query({ query: () => 'posts', providesTags: (result) => result ? result.map(({ id }) => ({ type: 'Posts', id })) : [], }), addPost: build.mutation>({ query: (body) => ({ url: `posts`, method: 'POST', body, }), invalidatesTags: ['Posts'], }), }), }) // Auto-generated hooks export const { useGetPostsQuery, useAddPostMutation } = api // Possible exports export const { endpoints, reducerPath, reducer, middleware } = api // reducerPath, reducer, middleware are only used in store configuration // endpoints will have: // endpoints.getPosts.initiate(), endpoints.getPosts.select(), endpoints.getPosts.useQuery() // endpoints.addPost.initiate(), endpoints.addPost.select(), endpoints.addPost.useMutation() // see `createApi` overview for _all exports_ ``` -------------------------------- ### Running RTK Codemods Globally with yarn Source: https://github.com/reduxjs/redux-toolkit/blob/master/packages/rtk-codemods/README.md This shows how to install and run RTK Codemods globally using yarn. After global installation, you can invoke the 'rtk-codemods' command with the transform name and target files. ```bash yarn global add @reduxjs/rtk-codemods rtk-codemods path/of/files/ or/some**/*glob.js ``` -------------------------------- ### Direct Endpoint Initiation with Manual Cleanup Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/usage/prefetching.mdx Shows how to use `endpoint.initiate()` directly for more control over data fetching and subscriptions. Unlike `api.util.prefetch`, `initiate()` defaults to `subscribe: true`, which creates a subscription that requires manual cleanup using `promise.unsubscribe()` to prevent memory leaks. This is useful for advanced subscription management. ```javascript import { api } from './api' // Assuming api is exported from './api' import { store } from './store' // Assuming store is exported from './store' const endpointName = 'someEndpoint' const arg = { some: 'argument' } // This creates a subscription that must be manually cleaned up const promise = store.dispatch( api.endpoints[endpointName].initiate(arg, { subscribe: true, // Creates a subscription (default) forceRefetch: true, }), ) // You must manually unsubscribe to prevent memory leaks // For example, in a useEffect cleanup function or component unmount // promise.unsubscribe() ``` -------------------------------- ### Bootstrap Next.js with Redux Toolkit Source: https://github.com/reduxjs/redux-toolkit/blob/master/examples/publish-ci/next/README.md Use these commands to initialize a new Next.js project pre-configured with Redux Toolkit. ```bash npx create-next-app --example with-redux with-redux-app ``` ```bash yarn create next-app --example with-redux with-redux-app ``` ```bash pnpm create next-app --example with-redux with-redux-app ``` -------------------------------- ### Setup RTK Query Listeners for Refetching Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/introduction/getting-started.md The setupListeners utility enables automatic refetching behaviors like refetchOnMount and refetchOnReconnect. It's a utility used with RTK Query to manage cache updates based on component lifecycle and network status. ```typescript import { setupListeners } from '@reduxjs/toolkit/query' import { pokemonApi } from './pokemonApi' setupListeners(store.dispatch) ``` -------------------------------- ### useInfiniteQueryState Hook Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/created-api/hooks.mdx Shows an example of accessing the `useInfiniteQueryState` hook from an API instance. This hook is used for managing state related to infinite queries, allowing for fetching and managing paginated data. ```typescript const useInfiniteQueryStateResult = api.endpoints.getManyPosts.useInfiniteQueryState(arg, options) ``` -------------------------------- ### Infinite Query Cache Structure Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/usage/infinite-queries.mdx This example illustrates the internal cache structure of an infinite query, showing how multiple pages and their corresponding page parameters are stored under a single cache key. ```typescript { queries: { "getPokemon('fire')": { data: { pages: [ ["Charmander", "Charmeleon"], ["Charizard", "Vulpix"], ["Magmar", "Flareon"] ], pageParams: [ 1, 2, 3 ] } } } } ``` -------------------------------- ### Accessing useQueryState Hook Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/created-api/hooks.mdx Illustrates how to access the `useQueryState` hook, which is an implementation detail for primary hooks. This example shows calling the hook with a specific endpoint and arguments to retrieve the current query state. ```typescript const useQueryStateResult = api.endpoints.getPosts.useQueryState(arg, options) ``` -------------------------------- ### setupListeners Default Configuration Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/setupListeners.mdx This function sets up listeners for focus and network events to enable automatic data refetching. It uses default handlers for `onFocus`, `onFocusLost`, `onOnline`, and `onOffline` actions. The listeners are added only once and an unsubscribe function is returned to clean them up. ```typescript let initialized = false export function setupListeners( dispatch: ThunkDispatch, customHandler?: ( dispatch: ThunkDispatch, actions: { onFocus: typeof onFocus onFocusLost: typeof onFocusLost onOnline: typeof onOnline onOffline: typeof onOffline }, ) => () => void, ) { function defaultHandler() { const handleFocus = () => dispatch(onFocus()) const handleFocusLost = () => dispatch(onFocusLost()) const handleOnline = () => dispatch(onOnline()) const handleOffline = () => dispatch(onOffline()) const handleVisibilityChange = () => { if (window.document.visibilityState === 'visible') { handleFocus() } else { handleFocusLost() } } if (!initialized) { if (typeof window !== 'undefined' && window.addEventListener) { // Handle focus events window.addEventListener( 'visibilitychange', handleVisibilityChange, false, ) window.addEventListener('focus', handleFocus, false) // Handle connection events window.addEventListener('online', handleOnline, false) window.addEventListener('offline', handleOffline, false) initialized = true } } const unsubscribe = () => { window.removeEventListener('focus', handleFocus) window.removeEventListener('visibilitychange', handleVisibilityChange) window.removeEventListener('online', handleOnline) window.removeEventListener('offline', handleOffline) initialized = false } return unsubscribe } return customHandler ? customHandler(dispatch, { onFocus, onFocusLost, onOffline, onOnline }) : defaultHandler() } ``` -------------------------------- ### Advanced Custom Store Setup with Persistence Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/usage/migrating-to-modern-redux.mdx Illustrates a complex store configuration including manual root reducer combination, custom middleware, thunk extra arguments, and integration with redux-persist. ```javascript import { configureStore, combineReducers } from '@reduxjs/toolkit' import { persistReducer } from 'redux-persist' import storage from 'redux-persist/lib/storage' import { api } from '../features/api/apiSlice' import { serviceLayer } from '../features/api/serviceLayer' const rootReducer = combineReducers({ posts: postsReducer, users: usersReducer, [api.reducerPath]: api.reducer, }) const persistConfig = { key: 'root', version: 1, storage } const persistedReducer = persistReducer(persistConfig, rootReducer) const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: { extraArgument: { serviceLayer } }, }), }) ``` -------------------------------- ### Simple Base Query TypeScript Example Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/usage-with-typescript.mdx Demonstrates how to implement and use a custom base query function with specific types for arguments, error, extra options, and metadata. This example shows conditional success and error responses. ```typescript import { createApi } from '@reduxjs/toolkit/query' import type { BaseQueryFn } from '@reduxjs/toolkit/query' const simpleBaseQuery: BaseQueryFn< string, // Args unknown, // Result { reason: string }, // Error { shout?: boolean }, // DefinitionExtraOptions { timestamp: number } // Meta > = (arg, api, extraOptions) => { // `arg` has the type `string` // `api` has the type `BaseQueryApi` (not configurable) // `extraOptions` has the type `{ shout?: boolean } const meta = { timestamp: Date.now() } if (arg === 'forceFail') { return { error: { reason: 'Intentionally requested to fail!', meta, }, } } if (extraOptions.shout) { return { data: 'CONGRATULATIONS', meta } } return { data: 'congratulations', meta } } const api = createApi({ baseQuery: simpleBaseQuery, endpoints: (build) => ({ getSupport: build.query({ query: () => 'support me', extraOptions: { shout: true, }, }), }), }) ``` -------------------------------- ### Infinite Query Definition Example (Pokemon API) Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/usage/infinite-queries.mdx An example demonstrating how to define an infinite query endpoint for a fictional Pokemon API. It showcases the use of `createApi`, `fetchBaseQuery`, and `infiniteQuery` with options like `initialPageParam`, `maxPages`, `getNextPageParam`, and `getPreviousPageParam`. ```typescript type Pokemon = { id: string name: string } const pokemonApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com/pokemon' }), endpoints: (build) => ({ // 3 TS generics: page contents, query arg, page param getInfinitePokemonWithMax: build.infiniteQuery({ infiniteQueryOptions: { // Must provide a default initial page param value initialPageParam: 1, // Optionally limit the number of cached pages maxPages: 3, // Must provide a `getNextPageParam` function getNextPageParam: ( lastPage, allPages, lastPageParam, allPageParams, queryArg, ) => lastPageParam + 1, // Optionally provide a `getPreviousPageParam` function getPreviousPageParam: ( firstPage, allPages, firstPageParam, allPageParams, queryArg, ) => { return firstPageParam > 0 ? firstPageParam - 1 : undefined }, }, // The `query` function receives `{queryArg, pageParam}` as its argument query({ queryArg, pageParam }) { return `/type/${queryArg}?page=${pageParam}` }, }), }), }) ``` -------------------------------- ### Basic Setup for Code Splitting Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/usage/code-splitting.mdx Initialize an empty RTK Query API service that can be used to inject endpoints later. This is useful for splitting endpoint definitions across multiple files. ```APIDOC ## Basic Setup for Code Splitting ### Description Initializes an empty RTK Query API service that can be used to inject endpoints later. This is useful for splitting endpoint definitions across multiple files. ### Method N/A (Initialization) ### Endpoint N/A (Initialization) ### Parameters N/A ### Request Example ```typescript // Or from '@reduxjs/toolkit/query' if not using the auto-generated hooks import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' // initialize an empty api service that we'll inject endpoints into later as needed export const emptySplitApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: () => ({}), }) ``` ### Response N/A ``` -------------------------------- ### Configure Store with Custom Middleware (JavaScript) Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/api/getDefaultMiddleware.mdx Shows how to provide a custom array of middleware to configureStore. When a custom list is provided, no default middleware is automatically included, and you are responsible for defining all desired middleware. ```javascript import { configureStore } from '@reduxjs/toolkit' const store = configureStore({ reducer: rootReducer, middleware: () => new Tuple(thunk, logger), }) ``` -------------------------------- ### Implementing ApiProvider in React Source: https://github.com/reduxjs/redux-toolkit/blob/master/docs/rtk-query/api/ApiProvider.mdx This example demonstrates how to wrap a React application with the ApiProvider. It initializes the API context for RTK Query, allowing components to access hooks without explicit store configuration. ```typescript import { ApiProvider } from '@reduxjs/toolkit/query/react'; import { api } from './api'; import { App } from './App'; export const Root = () => ( ); ```