TanStack Query · API boundary

TanStack Query snake_case ↔ camelCase

TanStack Query should cache the shape your application actually uses. Normalize snake_case API responses inside shared query functions and convert mutation variables back to snake_case in the request function.

By Camel Case Converter Editorial TeamPublished Sep 12, 2026Last reviewed

Return camelCase data from the query function

import { useQuery } from "@tanstack/react-query"
import { apiJson } from "./api"

type UserProfile = {
  userId: number
  firstName: string
}

export function useUserProfile(userId: number) {
  return useQuery({
    queryKey: ["user-profile", userId],
    queryFn: () => apiJson<UserProfile>(`/users/${userId}`),
  })
}

When the query function returns normalized data, every component reading that query key sees the same camelCase shape.

Convert mutation variables at the request boundary

import { useMutation, useQueryClient } from "@tanstack/react-query"
import { apiJson } from "./api"

type UpdateUser = {
  firstName: string
}

export function useUpdateUser(userId: number) {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: (input: UpdateUser) =>
      apiJson(`/users/${userId}`, {
        method: "PATCH",
        body: input,
      }),
    onSuccess: (data) => {
      queryClient.setQueryData(["user-profile", userId], data)
    },
  })
}

Keep mutation inputs typed in the application's camelCase model, then map them to the server's snake_case JSON contract inside the mutation function.

Production considerations

  • TanStack Query v5 uses the single options-object form for useQuery and useMutation.
  • Cache one canonical shape. Mixing raw snake_case and normalized camelCase under the same query key makes updates harder to reason about.
  • Normalize mutation responses before writing them into the cache.
  • Case conversion is a transport concern; React components should consume already-normalized domain data.

Test the JSON boundary online

Use the browser tool to test nested objects, arrays, excluded keys, stop paths, semantic prefixes, collision handling, and a key-only diff before you copy the same convention into an application.

Drop a .json file here or choose one from your device

Files are read only in your browser. Maximum file size: 5 MB.

Converted JSON
{
  "userProfile": {
    "firstName": "Ada",
    "createdAt": "2026-09-12"
  }
}

Parsing, file reading, formatting, and key conversion run locally in your browser. JSON input is not sent to a conversion server.