@@ -17,7 +17,7 @@ to represent the data expected.
1717
1818- ` Entity ` - represents a single unique object (denormalized)
1919- ` schema.Union(Entity) ` - polymorphic objects (A | B)
20- - ` {[key:string]: Schema} ` - immutable objects (lacking primary key)
20+ - ` {[key:string]: Schema} ` - immutable objects
2121- ` schema.Invalidate(Entity) ` - to delete an Entity
2222
2323### List
@@ -42,7 +42,6 @@ to represent the data expected.
4242- Every ` Entity ` subclass ** defines defaults** for _ all_ non-optional serialised fields.
4343- Override ` pk() ` only when the primary key ≠ ` id ` .
4444- ` pk() ` return type is ` number | string | undefined `
45- - if ` pk() ` cannot be determined, use ` {[key:string]: Schema} ` schema instead
4645- Always define nested Entities to be used in ` static schema `
4746 - When designing APIs, prefer nesting entities
4847- use ` static schema ` to deserialize
@@ -75,7 +74,6 @@ export class Todo extends Entity {
7574 completed = false ;
7675
7776 static key = ' Todo' ;
78- // optional
7977 static schema = {
8078 user: User ,
8179 }
@@ -102,6 +100,11 @@ const todo = useSuspense(TodoResource.get, { id: 5 });
102100const todoList = useSuspense (TodoResource .getList );
103101// GET https://jsonplaceholder.typicode.com/todos?userId=1
104102const todoListByUser = useSuspense (TodoResource .getList , { userId: 1 });
103+ // subscriptions
104+ const todo = useLive (TodoResource .get , { id: 5 });
105+ // without fetch
106+ const todo = useCache (TodoResource .get , { id: 5 });
107+ const todo = useQuery (Todo , { id: 5 });
105108```
106109
107110#### Mutations
@@ -124,24 +127,30 @@ const deleteTodo = id => ctrl.fetch(TodoResource.delete, { id });
124127const getNextPage = (page ) => ctrl .fetch (TodoResource .getList .getPage , { userId: 1 , page })
125128```
126129
130+ #### Type-safe imperative actions
131+
132+ ` Controller ` is returned from ` useController() ` . It has: ctrl.fetch(), ctrl.fetchIfStale(), ctrl.expireAll(), ctrl.invalidate(), ctrl.invalidateAll(), ctrl.setResponse(), ctrl.set().
133+
127134#### Programmatic queries
128135
129136``` ts
130137const queryRemainingTodos = new schema .Query (
131138 TodoResource .getList .schema ,
132139 entries => entries .filter (todo => ! todo .completed ).length ,
133140);
141+
142+ const allRemainingTodos = useQuery (queryRemainingTodos );
143+ const firstUserRemainingTodos = useQuery (queryRemainingTodos , { userId: 1 });
134144```
135145
136146``` ts
137147const groupTodoByUser = new schema .Query (
138148 TodoResource .getList .schema ,
139149 todos => Object .groupBy (todos , todo => todo .userId ),
140150);
151+ const todosByUser = useQuery (groupTodoByUser );
141152```
142153
143- For more detailed usage, refer to the [ @data-client/react guide] ( .github/instructions/react.instructions.md ) .
144-
145154---
146155
147156## 4. Custom RestEndpoint patterns
@@ -160,6 +169,7 @@ export const getTicker = new RestEndpoint({
160169- ` path ` params ▶️ 1st arg shape.
161170- ` method ` ≠ ` GET ` ⇒ 2nd arg = body (unless ` body: undefined ` ).
162171- Provide ` searchParams ` / ` body ` _ values_ purely for ** type inference** .
172+ - Use ` RestGenerics ` when inheriting from ` RestEndpoint ` .
163173
164174### getOptimisticResponse()
165175
@@ -224,9 +234,13 @@ export const IssueResource = resource({
224234
225235## 8. Best Practices & Notes
226236
237+ - When asked to browse or navigate to a web address, actual visit the address
227238- Always set up ` schema ` on every resource/entity/collection for normalization.
228239- Prefer ` RestEndpoint ` over ` resource ` for defining single endpoints or when full CRUD endpoints don't exist
229240- Normalize deeply nested or relational data by defining proper schemas.
241+ - ` useDebounce(query, timeout); ` when rendering async data based on user field inputs
242+ - ` [handleSubmit, loading, error] = useLoading() ` when tracking mutation loads like submitting an async form
243+ - Prefer smaller React components that do one thing.
230244
231245## 9. Common Mistakes to Avoid
232246
0 commit comments