import { toast } from '@renderer/components/ui/toast';
import { ipc } from '@renderer/ipc';
import { QueryClient, queryOptions, useMutation } from '@tanstack/react-query';
import {
createRootRouteWithContext,
createRouter,
} from '@tanstack/react-router';
interface MyRouterContext {
queryClient: QueryClient;
}
const rootRoute = createRootRouteWithContext<MyRouterContext>()({
component: App,
});
const queryClient = new QueryClient();
const router = createRouter({
routeTree: rootRoute,
context: {
queryClient,
queryOptions: {
projects: {
list: (props: ListProjectsProps) => {
return queryOptions({
queryKey: ['projects', 'list', props],
queryFn: async () => {
const projects = await ipc.core.projects.list(props);
projects.forEach((project) => {
queryClient.setQueryData(['projects', project.id], project);
});
},
});
},
read: (props: ReadProjectProps) => {
return queryOptions({
queryKey: ['projects', props],
queryFn: () => ipc.core.projects.read(props),
});
},
},
},
mutations: {
projects: {
useUpdate: (props: UpdateProjectProps) =>
useMutation({
mutationFn: () => ipc.core.projects.update(props),
onSuccess: (project) => {
// ✅ update the project without additional requests
queryClient.setQueryData(['projects', { id: props.id }], project);
// @todo maybe invalidate the list query?
toast.success('Project updated successfully', {
description: `Project ${project.name} has been updated.`,
});
},
onError: (error) => {
toast.error('Failed to update project', {
description: error.message,
});
},
}),
},
},
},
});
// src/routes/projects/$projectId.tsx
export const Route = createFileRoute('/projects/$projectId')({
component: ProjectLayout,
loader: async ({ context, params }) => {
await context.queryClient.ensureQueryData(context.queryOptions.projects.read({id: params.projectId}))
},
});
function ProjectLayout() {
const params = Route.useParams();
const context = Route.useRouteContext();
const {data: project} = useSuspenseQuery(context.queryOptions.projects.read({id: params.projectId}));
...
}