React Query

redmine-api-client-react, TanStack Query options and hooks for the Redmine client.

redmine-api-client-react provides queries for TanStack Query, one module per resource, and hooks for paged lists.

Installation

pnpm add redmine-api-client redmine-api-client-react @tanstack/react-query

It works with React 18 and 19, and TanStack Query 5.

Setup

Provide the client

Wrap your app in a QueryClientProvider and a RedmineClientProvider:

main.tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RedmineClient } from "redmine-api-client";
import { RedmineClientProvider } from "redmine-api-client-react";

const queryClient = new QueryClient();
const redmine = new RedmineClient("https://redmine.example.com", { key: apiKey });

export function Root() {
  return (
    <QueryClientProvider client={queryClient}>
      <RedmineClientProvider client={redmine}>
        <App />
      </RedmineClientProvider>
    </QueryClientProvider>
  );
}

Query

Get the client with useRedmineClient() and pass a query to useQuery:

Issue.tsx
import { useQuery } from "@tanstack/react-query";
import { redmineIssueQuery, useRedmineClient } from "redmine-api-client-react";

export function Issue({ id }: { id: number }) {
  const client = useRedmineClient();
  const { data: issue, isPending } = useQuery(redmineIssueQuery(client, id));

  if (isPending) return <p>Loading…</p>;
  return <h1>{issue?.subject}</h1>;
}

Invalidate after changes

Each resource has a filter that matches all of its queries:

import { useMutation, useQueryClient } from "@tanstack/react-query";
import { redmineIssuesQueries, useRedmineClient } from "redmine-api-client-react";

const client = useRedmineClient();
const queryClient = useQueryClient();

const closeIssue = useMutation({
  mutationFn: (id: number) => client.issuesClient.updateIssue(id, { issue: { statusId: 5 } }),
  onSuccess: () => queryClient.invalidateQueries(redmineIssuesQueries),
});

Why queries, not hooks?

The queries are plain TanStack Query options, so they work with useQuery, useSuspenseQuery, prefetchQuery, ensureQueryData and getQueryData, e.g. in a router loader:

await queryClient.ensureQueryData(redmineProjectQuery(client, "my-project"));

On this page