Seems like the internet has chosen one winner.

React Query

Transform the API responses in queryFn before returning.
Transform the API responses using select transformations.
javascript
const transformTodoNames = (data: Todos) => data.map((todo) => todo.name.toUpperCase()) export const useTodosQuery = () => useQuery({ queryKey: ['todos'], queryFn: fetchTodos, // โœ… uses a stable function reference select: transformTodoNames, }) export const useTodosQuery = () => useQuery({ queryKey: ['todos'], queryFn: fetchTodos, // โœ… memoizes with useCallback select: React.useCallback( (data: Todos) => data.map((todo) => todo.name.toUpperCase()), [] ), })
Use persistQueryClient to save your cache in localStorage.
After a mutation is finished, you often need to do a dependent action.
So, either use a callback myMutation.mutate(data, { onSuccess: callback })
or mutateAsync await myMutation.mutateAsync(data)