Redux toolkit query or RTK query is the greatest human invention since the wheel. It simplifies performing asynchronous tasks such as fetching data from an API. In this article, I will show you how I use it and enjoy the full benefits.
Check out my tutorial on setting up rtk query
Globally transform Response
I was working on a project one day and I wanted to be able to (globally) define a transformResponse for all queries endpoint.
After my research I came up with a solution.
In your API slice, you can change the response for all the endpoints. To do this, you wrap your baseQuery
with a custom function that does these transformations. reference
const baseQueryWithChange = async (args, api, extraOptions) => {
let result = await baseQuery(args, api, extraOptions);
if (result.data) {
result.data = result.data.data
}
return result
}
wrap baseQuery
with the baseQueryWithChange
function
export const apiSlice = createApi({
baseQuery: baseQueryWithChange,
endpoints: builder => ({})
})
transformResponse for each endpoint
This one is easy, for each endpoint you inject to your API slice, you can transform the response of the API call.
import { apiSlice } from "../../app/api/apiSlice";
export const extendedApiSlice = apiSlice.injectEndpoints({
endpoints: builder => ({
getHistory: builder.query({
query: credentials => ({
url: `/history/${credentials.id}`,
method: "GET"
}),
providesTags: ["History"],
transformResponse: (response) => response.result,
})
})
})
export const {
useGetHistoryQuery
} = extendedApiSlice
refetch();
refetch
: A function returned by the query hooks. Triggers a refetch (usually to be called inside useEffect
).
With this function, I can make an API call every ten seconds. reference
// stocks component
import { useGetStocksQuery } from '../features/stocksList/stocksListApiSlice';
import { useEffect, useRef } from "react";
const Stocks = () => {
const tickerArray = [
"AAPL",
"TSLA",
"NKE",
"MSFT",
"AMZN",
"PLTR",
"BYND",
"GOOGL",
"META",
"SNAP",
"NFLX"
];
// store the timer inside useRef hook to ensure persistentence
const stockTimerId = useRef();
let {
data: list,
refetch
} = useGetStocksQuery({tickerArray});
useEffect(() => {
stockTimerId.current = await setInterval(() => refetch(), 10000);
}
// when component unmounts clear the interval
return () => clearInterval(stockTimerId.current)
})
return (
<>Your JSX goes here</>
)
}
export default Stocks
Query params RTK query
How to query with multiple query parameters?
If I want to make my URL to look like this https://api.coingecko.com/api/v3/coins/markets?vs_currency=ngn&order=market_cap_desc&per_page=100&page=1&sparkline=false
baseURL: https://api.coingecko.com/api/v3/coins/markets
Query Parameters: ?vs_currency=ngn&order=market_cap_desc&per_page=100
We can achieve this in RTK query, by creating an object that contains all the query paramters, and passing it as an option into the hook.
const queryParams = {
vs_currency: "usd",
order: "market_cap_desc",
page: "1",
sparkline: "false",
ids: debouncedSearchQuery,
price_change_percentage: "1"
}
const { data: coinSearchResult, isSuccess: searchedForCoin } = useGetCoinQuery(queryParams)
// apiSlice
getCoins: builder.query({
query: (arg) => ({
url: `/coins/markets`,
params: {...arg}
}),
})
Stackoverflow question: RTK Query query parameter
Second question: Redux Toolkit RTK Query sending query parameters
Path params RTK query
How to query with multiple path parameters?
If I want to make my URL look like this https://api.coingecko.com/api/v3/coins/bitcoin
baseURL: https://api.coingecko.com/api/v3/coins
Path Params: /bitcoin/usd
query accepts only one argument, you use an object that contains all your path parameters when using the automatically generated hooks.
// apiSlice
getReport: builder.query({
query: ({bitcoin, currency}) =>
`/${bitcoin}/${currency}`,
}),
useGetReportQuery({
bitcoin,
currency
});
GitHub issue: How to query with multiple path parameters
Option: skip in RTK query
I want to search through an array based on an input field provided in the app.
I have a useSearchMovieQuery
in RTK Query API which search for whatever a user enters in the search field. I want to prevent the query from running on the initial render, which can be achieved by skipping the query using "skip"
or "skipToken"
.
I want only to run this query after the user stops typing, not immediately after onChange event in the search field.
solution
We can delay fetching data in RTK query until some condition becomes true. If you want to prevent a query from automatically running, you can use the skip
parameter in a hook.
To achieve this we use a custom react hook useDebounce
which will return the user input after 500ms.
This query will not run until the user types something into the search box.
const [searchQuery, setSearchQuery] = useState("");
// custom hook
const debouncedSearchQuery = useDebounce(searchQuery, 500);
const {
data: searchResult,
isSuccess: searchedForMovie,
isFetching,
isError,
} = useSearchMovieQuery(debouncedSearchQuery, { skip: debouncedSearchQuery === "" });
Stackoverflow question: rtk-query-run-query-only-after-user-stops-typing-in-search-field
second question: How to disable RTK Query auto-request fetching?
You can learn more about useDebounce
hook here
References
How to use transformResponse props with injectEndpoints
Thank You, Please follow me
Top comments (0)