22
33React Query Tree lets you define your API as a tree of queries and mutations, with fully typed queryKeys and a slim API for accessing them.
44
5+ > React Query Tree is heavily inspired by the tRPC React Query client. It provides the same type-safe, hierarchical developer experience, but is designed for client-side use cases where a tRPC server is not required.
6+
7+ <br />
8+
59** ☹️ Traditional method**
610
711- Query keys and path keys are not typed
@@ -11,9 +15,7 @@ React Query Tree lets you define your API as a tree of queries and mutations, wi
1115const todosQuery = useQuery ({
1216 queryKey: [" todos" , " list" ],
1317 queryFn : () => {
14- return fetch (" https://jsonplaceholder.typicode.com/todos" ).then ((res ) =>
15- res .json ()
16- );
18+ return fetch (" /todos" );
1719 },
1820});
1921```
@@ -28,13 +30,13 @@ const todosQuery = useQuery({
2830** api.ts**
2931
3032``` ts
31- export const api = createClient ({
33+ import { createApi , query } from " react-query-tree" ;
34+
35+ export const api = createApi ({
3236 todos: {
3337 list: query ({
34- queryFn : async () => {
35- return fetch (" https://jsonplaceholder.typicode.com/todos" ).then ((res ) =>
36- res .json ()
37- );
38+ queryFn : () => {
39+ return fetch (" /todos" );
3840 },
3941 }),
4042 },
@@ -49,6 +51,96 @@ const todosQuery = useQuery(api.todos.list.queryOptions());
4951
5052## API Documentation
5153
52- ### Collections and client
54+ ### Nested APIs
55+
56+ To avoid making the API object huge you can split it into smaller chunks that are then used the main API object.
57+
58+ ``` ts
59+ import { createApi , query } from " react-query-tree" ;
60+
61+ const todosApi = createApi ({
62+ list: query ({
63+ queryFn : () => {
64+ return fetch (" /todos" );
65+ },
66+ }),
67+ });
68+
69+ const usersApi = createApi ({
70+ list: query ({
71+ queryFn : () => {
72+ return fetch (" /users" );
73+ },
74+ }),
75+ });
76+ export const api = createApi ({
77+ todos: todosApi ,
78+ users: usersApi ,
79+ });
80+ ```
81+
82+ ### Invalidation
83+
84+ Invalidating a query.
85+
86+ ``` ts
87+ queryClient .invalidateQueries ({ queryKey: api .todos .list .queryKey () });
88+ ```
89+
90+ Invalidating a path (all nested queries inside that object).
91+
92+ ``` ts
93+ queryClient .invalidateQueries ({ queryKey: api .todos .pathKey () });
94+ ```
95+
96+ Invalidating inside an API.
97+
98+ ``` ts
99+ const todosApi = createApi ({
100+ list: query ({
101+ queryFn : () => {
102+ return fetch (" /todos" ).then ((res ) => res .json ());
103+ },
104+ }),
105+ create: mutation ({
106+ mutationFn : (todo ) => {
107+ return fetch (" /todos" , {
108+ method: " POST" ,
109+ body: JSON .stringify (todo ),
110+ });
111+ },
112+ onSuccess : () => {
113+ queryClient .invalidateQueries ({ queryKey: api .todos .pathKey () });
114+ },
115+ }),
116+ });
117+ ```
118+
119+ ### Query and Mutation options
120+
121+ You can add query and mutation option directly inside your API.
122+
123+ ``` ts
124+ const todosApi = createApi ({
125+ list: query ({
126+ queryFn : () => {
127+ return fetch (" /todos" ).then ((res ) => res .json ());
128+ },
129+ staleTime: 10_000 ,
130+ retry: false ,
131+ }),
132+ });
133+ ```
134+
135+ These can be extended when consuming the API.
136+
137+ ``` ts
138+ useQuery (
139+ todosApi .list .queryOptions ({
140+ staleTime: 5_000 ,
141+ })
142+ );
143+ ```
53144
54- To avoid making the api object huge you can split it into collections and move to separate files.
145+ - Primitive values will override the base options.
146+ - Functions such as ` onSuccess ` will be merged.
0 commit comments