DEV Community

Cover image for RTK Query: How to modify query responses with transformResponse
Yuko
Yuko

Posted on

RTK Query: How to modify query responses with transformResponse

This is my note when I learned how to customize raw API responses with the transformResponse.

According to the official document,

Individual endpoints on createApi accept a transformResponse property which allows manipulation of the data returned by a query or mutation before it hits the cache.

FYI: RTK Query has a feature for managing cached data that saves the data in the Redux store as a cache for reuse when another request is made for the same data.

transformResponse

By default, transformResponse receives a baseQuery return value (, and potentially meta and arg) from baseQuery and returns it unchanged without any manipulation

    function defaultTransformResponse(
      baseQueryReturnValue: unknown,
      meta: unknown,
      arg: unknown
    ) {
      return baseQueryReturnValue
    }

    ref: https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#customizing-query-responses-with-transformresponse
Enter fullscreen mode Exit fullscreen mode

You can modify the baseQuery return value within the transformResponse function.

Code Example

Here is my code example:
1) Retrieve Star Wars characters data from the following URL: https://akabab.github.io/starwars-api/api
2) Clean up unnecessary data, add a label of either “ABY” or “BBY” for the year information, and include Body Mass Index (BMI) data.
3) Change the data structure

    // from
    [
      {
        id: 1,
        name: Name,
        species: SpeciesName
        year: -2,
        ...
      },
      {
        ...
      },
      ...
    ]
    // to 
    {
      SpeciesName:[
        {
          id: 1,
          name: Name,
          species: SpeciesName,
          year: "2 BBY"
          ...
        },
        ...
      ],
      [
        ...
      ],
      ...
    }
Enter fullscreen mode Exit fullscreen mode

API slice

You will use the transformResponse property in the API slice.

    import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
    import {
      RowCharacter,
      CategorizedCharacters,
      ModifiedCharacter
    } from "./starWars-types";
    import { modifyRowCharacters, categorizeCharacters } from "./starWars-utils";

    export const starWarsApi = createApi({
      reducerPath: "starWarsApi",
      baseQuery: fetchBaseQuery({
        baseUrl: "https://akabab.github.io/starwars-api/api/"
      }),
      endpoints: (builder) => ({
        getCharacters: builder.query<CategorizedCharacters, undefined>({
          query: () => "all.json",
          transformResponse: (response: RowCharacter[]): CategorizedCharacters => {
            if (response.length === 0) return {};
            const modifiedCharacters = modifyRowCharacters(response);
            const categorizedCharacters = categorizeCharacters(modifiedCharacters);
            return { all: modifiedCharacters, ...categorizedCharacters };
          }
        })
      })
    });
Enter fullscreen mode Exit fullscreen mode

modifyRowCharacters

This code corresponds to the second process the above.

    export const modifyRowCharacters = (
      characters: RowCharacter[]
    ): ModifiedCharacter[] => {
      const modifiedCharacters: ModifiedCharacter[] = [];
      const calcBMI = (height: number, mass: number): number =>
        +(mass / Math.pow(height, 2)).toFixed(2);
      const convertToStarWarsDating = (year: number) =>
        year > 0 ? `${year} ABY` : `${Math.abs(year)} BBY`;
      for (const character of characters) {
        const bmi =
          character.height && character.mass
            ? calcBMI(character.height, character.mass)
            : undefined;
        modifiedCharacters.push({
          id: character.id,
          name: character.name,
          image: character.image,
          gender: character.gender,
          species: character.species,
          ...(bmi && {
            bmi,
            height: character.height,
            mass: character.mass
          }),
          ...(character.homeworld && { homeworld: character.homeworld }),
          ...(character.born && { born: convertToStarWarsDating(+character.born) }),
          ...(character.died && { died: convertToStarWarsDating(+character.died) })
        });
      }
      return modifiedCharacters;
    };
Enter fullscreen mode Exit fullscreen mode

categorizeCharacters

This code is for the third process.

    export const categorizeCharacters = (
      characters: ModifiedCharacter[]
    ): CategorizedCharacters => {
      const categorizedCharacters = characters.reduce(
        (acc: CategorizedCharacters, character: ModifiedCharacter) => {
          if (acc[character.species]) {
            acc[character.species].push(character);
            return acc;
          }
          acc[character.species] = [character];
          return acc;
        },
        {}
      );
      return categorizedCharacters;
    };
Enter fullscreen mode Exit fullscreen mode

Thank you for reading :)
The entire code is available here.
The original article is here

Billboard image

The fastest way to detect downtimes

Join Vercel, CrowdStrike, and thousands of other teams that trust Checkly to streamline monitoring.

Get started now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay