Last active
November 30, 2025 07:15
-
-
Save whoisYeshua/1f8b63245fad36a13bd791daa839326e to your computer and use it in GitHub Desktop.
@reduxjs/toolkit/query example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { createAppSelector } from '$store/utils'; | |
| import { charactersTransaction } from './transaction'; | |
| const transactionSelector = charactersTransaction.endpoints.getCharacters.select(); | |
| const charactersResult = createAppSelector( | |
| transactionSelector, | |
| (result: { | |
| data?: { results?: Array<{ id: number; name: string; status: string; gender: string }> }; | |
| }) => result.data?.results | |
| ); | |
| export const deadMalesCharacters = createAppSelector( | |
| charactersResult, | |
| (characters: Array<{ id: number; name: string; status: string; gender: string }> | undefined) => | |
| characters?.filter( | |
| (character: { id: number; name: string; status: string; gender: string }) => | |
| character.status === 'Dead' && character.gender === 'Male' | |
| ) | |
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { charactersResponseSchema } from '$models/characters' | |
| import { transactions } from '$store/transactions' | |
| export const charactersTransaction = transactions.injectEndpoints({ | |
| endpoints: build => ({ | |
| getCharacters: build.query({ | |
| query: (_: void) => '/character', | |
| responseSchema: charactersResponseSchema, | |
| }), | |
| }), | |
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Box, Heading, Spinner, Alert, VStack, HStack } from '@chakra-ui/react' | |
| import { useAppSelector } from '../../../store/utils' | |
| import { charactersTransaction, charactersSelector } from './store' | |
| export const Characters = () => { | |
| const { data, isLoading, isError } = charactersTransaction.useGetCharactersQuery() | |
| const deadMalesCharacters = useAppSelector(charactersSelector.deadMalesCharacters) | |
| if (isLoading) | |
| return ( | |
| <Box textAlign="center" py={4}> | |
| <Spinner size="lg" /> | |
| <Box mt={2}>Loading characters...</Box> | |
| </Box> | |
| ) | |
| if (isError) | |
| return ( | |
| <Alert.Root status="error"> | |
| <Alert.Indicator /> | |
| <Alert.Content> | |
| <Alert.Title>Error!</Alert.Title> | |
| <Alert.Description>Error loading characters</Alert.Description> | |
| </Alert.Content> | |
| </Alert.Root> | |
| ) | |
| return ( | |
| <HStack align="start"> | |
| <VStack gap={2} mb={4} align="stretch"> | |
| <Heading as="h2" size="md" mb={3}> | |
| Characters | |
| </Heading> | |
| {data?.results.slice(0, 10).map(character => ( | |
| <Box key={character.id} p={2} border="1px solid" borderColor="gray.600" borderRadius="md"> | |
| {character.name} | |
| </Box> | |
| ))} | |
| </VStack> | |
| <VStack gap={2} align="stretch"> | |
| <Heading as="h2" size="md" mb={3}> | |
| Dead Males Characters | |
| </Heading> | |
| {deadMalesCharacters?.map((character: { id: number; name: string }) => ( | |
| <Box key={character.id} p={2} border="1px solid" borderColor="gray.600" borderRadius="md"> | |
| {character.name} | |
| </Box> | |
| ))} | |
| </VStack> | |
| </HStack> | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { episodesResponseSchema } from '$models/episodes' | |
| import { transactions } from '$store/transactions' | |
| export const episodesTransaction = transactions.injectEndpoints({ | |
| endpoints: (build) => ({ | |
| getEpisodes: build.query({ | |
| query: (_: void) => `/episode`, | |
| responseSchema: episodesResponseSchema | |
| }) | |
| }) | |
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Alert, Box, Heading, Spinner, VStack } from '@chakra-ui/react'; | |
| import { episodesTransaction } from './transaction'; | |
| export const Episodes = () => { | |
| const { isLoading, isError, data } = episodesTransaction.useGetEpisodesQuery(); | |
| if (isLoading) | |
| return ( | |
| <Box textAlign="center" py={4}> | |
| <Spinner size="lg" /> | |
| <Box mt={2}>Loading episodes...</Box> | |
| </Box> | |
| ); | |
| if (isError) | |
| return ( | |
| <Alert.Root status="error"> | |
| <Alert.Indicator /> | |
| <Alert.Content> | |
| <Alert.Title>Error!</Alert.Title> | |
| <Alert.Description>Error loading episodes</Alert.Description> | |
| </Alert.Content> | |
| </Alert.Root> | |
| ); | |
| return ( | |
| <Box> | |
| <Heading as="h2" size="md" mb={3}> | |
| Episodes | |
| </Heading> | |
| <VStack gap={2} align="stretch"> | |
| {data?.results.slice(0, 10).map((episode) => ( | |
| <Box key={episode.id} p={2} border="1px solid" borderColor="gray.600" borderRadius="md"> | |
| {episode.episode} — {episode.name} | |
| </Box> | |
| ))} | |
| </VStack> | |
| </Box> | |
| ); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { configureStore } from '@reduxjs/toolkit' | |
| import { setupListeners } from '@reduxjs/toolkit/query/react' | |
| import { router } from '$router' | |
| import { transactions } from './transactions' | |
| export const extraArgument = { router } | |
| export const store = configureStore({ | |
| reducer: { | |
| // Add the generated reducer as a specific top-level slice | |
| [transactions.reducerPath]: transactions.reducer, | |
| }, | |
| // Adding the api middleware enables caching, invalidation, polling, | |
| // and other useful features of `rtk-query`. | |
| middleware: getDefaultMiddleware => | |
| getDefaultMiddleware({ serializableCheck: false, thunk: { extraArgument } }).concat( | |
| transactions.middleware | |
| ), | |
| }) | |
| // optional, but required for refetchOnFocus/refetchOnReconnect behaviors | |
| // see `setupListeners` docs - takes an optional callback as the 2nd arg for customization | |
| setupListeners(store.dispatch) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { createApi, fetchBaseQuery, type QuerySubState } from '@reduxjs/toolkit/query/react' | |
| // initialize an empty api service that we'll inject endpoints into later as needed | |
| export const transactions = createApi({ | |
| reducerPath: 'transactions', | |
| baseQuery: fetchBaseQuery({ | |
| baseUrl: 'https://rickandmortyapi.com/api', | |
| prepareHeaders: (headers, api) => { | |
| console.log(api) | |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | |
| type Endpoints = Record<string, { select: () => (state: any) => QuerySubState<any, any> }> | |
| const currentEndpointSelector = (transactions.endpoints as Endpoints)[api.endpoint].select() | |
| if (currentEndpointSelector) { | |
| const currentEndpoint = currentEndpointSelector(api.getState()) | |
| const requestId = currentEndpoint?.requestId | |
| if (requestId) { | |
| headers.set('Rest-Id', requestId) | |
| } | |
| } | |
| return headers | |
| }, | |
| }), | |
| endpoints: () => ({}), | |
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { createAsyncThunk } from '@reduxjs/toolkit' | |
| import { useDispatch, useSelector } from 'react-redux' | |
| import { createSelector } from 'reselect' | |
| import type { extraArgument, store } from './store' | |
| export type RootState = ReturnType<typeof store.getState> | |
| export type AppDispatch = typeof store.dispatch | |
| export type ReduxExtraArgument = typeof extraArgument | |
| export const useAppDispatch = useDispatch.withTypes<AppDispatch>() | |
| export const useAppSelector = useSelector.withTypes<RootState>() | |
| export const createAppSelector = createSelector.withTypes<RootState>() | |
| export const createAppAsyncThunk = createAsyncThunk.withTypes<{ | |
| state: RootState | |
| dispatch: AppDispatch | |
| extra: ReduxExtraArgument | |
| }>() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment