How to use RTK query in Redux toolkit
Tags: react, redux, javascript, tutorial
Published: 2022-07-29 12:08:00

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](https://dev.to/masterifeanyi/how-to-setup-redux-tool-kit-for-rtk-query-2o69)



![BMC logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14on7b24aivsvgcld8k1.gif)

## 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](https://stackoverflow.com/questions/71503552/rtk-query-transform-all-query-responses-at-once/) 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](https://github.com/reduxjs/redux-toolkit/issues/1550#issuecomment-967119531)

```javascript
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

```javascript
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.

```javascript
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](https://stackoverflow.com/questions/71231118/refetching-upon-a-button-click-in-rtk-query-does-not-trigger-component-update)

```javascript
// 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.

```javascript

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](https://stackoverflow.com/questions/70081202/rtk-query-query-parameter)

Second question: [Redux Toolkit RTK Query sending query parameters](https://stackoverflow.com/questions/68158110/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.

```javascript

   // apiSlice

    getReport: builder.query({
      query: ({bitcoin, currency}) =>
        `/${bitcoin}/${currency}`,
    }),
        
    useGetReportQuery({
      bitcoin,
      currency
    });
```

GitHub issue: [How to query with multiple path parameters](https://github.com/reduxjs/redux-toolkit/issues/1028)


## 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.

```javascript

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](https://stackoverflow.com/questions/72502994/rtk-query-run-query-only-after-user-stops-typing-in-search-field)

second question: [How to disable RTK Query auto-request fetching?](https://stackoverflow.com/questions/72382502/how-to-disable-rtk-query-auto-request-fetching)

You can learn more about `useDebounce` hook [here](https://dev.to/ohdylan/create-a-debounce-hook-for-search-box-auto-completion-11n1)


**References**

[RTK query best practices](https://medium.com/nmc-techblog/rtk-query-best-practices-e0296d1679e6)

[How to use transformResponse props with injectEndpoints](https://stackoverflow.com/questions/69523004/react-toolkit-query-how-to-use-transformresponse-props-with-injectendpoints)

**Thank You, Please follow me**

<a href="https://www.buymeacoffee.com/ifeanyichima" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>

[twitter](https://twitter.com/ifeanyiTchima)
[github](https://github.com/MasterIfeanyi)
[linkedin](https://www.linkedin.com/in/ifeanyi-thankgod-chima/)