When using React Query, for the same query, you can either copy paste the code into different components or abstract it into a custom hook. The first one is just bad practice and the second method become unmanageable very quickly as your app (and # of endpoints) grows.
With TSRQ, you only define you write code for your queries and mutations once and reuse them wherever you want.
npm:
npm i -S tsrq react-query
yarn:
yarn add tsrq react-query
import {
createQueryBuilder,
createUseQuery,
createUseMutation,
} from "typed-query";
interface ITodo {
id: string;
title: string;
}
const builder = createQueryBuilder()
.query("todos", async () => {
return await fetch("/todos").then(res => res.json() as Array<ITodo>);
})
.query("byId", async (id: string) => {
return await fetch(`/todos/${id}`).then(res => res.json() as ITodo);
})
.mutation("updateTodo", async ({ id, title }: ITodo) => {
return await fetch(`/todos/${id}`, {
method: "PATCH",
body: JSON.stringify({ title }),
}).then(res => res.json() as ITodo);
});
const useQuery = createUseQuery(builder);
const useMutation = createUseMutation(builder);
export default function TodosList() {
// If query requires no parameters then you must
// provide an empty array
const { data } = useQuery("todos", []);
return (
<ul>
{data?.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}
export default function TodoPage({ id }: { id: string }) {
// Provide query parameters as array in second arg
const { data } = useQuery("byId", [id]);
const { mutate } = useMutation("updateTodo");
return <div>{data?.title}</div>;
}
- createQueryBuilder
Create instance:
import { createQueryBuilder } from "tsrq";
const builder = createQueryBuilder();
Add Query to Instance:
import { createQueryBuilder } from "tsrq";
const builder = createQueryBuilder().query("todos", () => {
return fetch("/todos").then(res => res.json());
});
Add Mutation to Instance:
import { createQueryBuilder } from "tsrq";
const builder = createQueryBuilder().mutation("add", (title: string) => {
return fetch("/todos", {
method: "POST",
body: JSON.stringify({
title,
}),
});
});
- createUseQuery
import { createQueryBuilder, createUseQuery } from "tsrq";
// Builder Code
const builder = createQueryBuilder();
// ...End Builder Code
export const useQuery = createUseQuery(builder);
Usage:
When query requires params:
import * as React from "react";
import { useQuery } from "./tsrq.config";
const TodoPage = ({ id }: { id: string }) => {
const { data, isLoading } = useQuery("byId", [id]);
if (isLoading) return null;
return <div>{/** JSX */}</div>;
};
When query doesn't require params:
import * as React from "react";
import { useQuery } from "./tsrq.config";
export default function TodosList() {
// If query requires no parameters then you must
// provide an empty array
const { data } = useQuery("todos", []);
return (
<ul>
{data?.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}
- createUseMutation
import { createQueryBuilder, createUseMutation } from "tsrq";
// Builder Code
const builder = createQueryBuilder();
// ...End Builder Code
export const useMutation = createUseMutation(builder);
Usage:
import * as React from "react";
import { useMutation } from "./tsrq.config";
const CreateTodoPage = () => {
const [title, setTitle] = React.useState("");
const { mutate } = useMutation("add");
const addTodo = () => {
mutate(title);
};
return <div>{/** JSX */}</div>;
};
- Alex Johansson (@katt) for tRPC. This library is heavily inspired by
trpc
. TSRQ QueryBuilder implementation is similar to TRPC's Router implementation.