@@ -30,69 +30,114 @@ response for use with [useQuery](/docs/api/useQuery)
30
30
31
31
## Usage
32
32
33
- ### Sorting & Filtering
33
+ ### Maintaining sort after creates {#sorting}
34
34
35
- <HooksPlayground groupId="schema" defaultOpen="y" fixtures={[
36
- {
37
- endpoint: new RestEndpoint({path: '/users'}),
38
- args: [ ] ,
39
- response: [
40
- { id: '123', name: 'Jim' },
41
- { id: '456', name: 'Jane' },
42
- { id: '777', name: 'Albatras', isAdmin: true },
43
- ] ,
44
- delay: 150,
45
- },
46
- ] }>
35
+ import { postFixtures,getInitialInterceptorData } from '@site/src /fixtures/posts-collection';
47
36
48
- ``` ts title="api/User.ts" collapsed
49
- export class User extends Entity {
37
+ Here we have an API that sorts based on the ` orderBy ` field. By wrapping our [ Collection] ( ./Collection.md )
38
+ in a ` Query ` that sorts, we can ensure we maintain the correct order after [ pushing] ( ./RestEndpoint.md#push )
39
+ new posts.
40
+
41
+ Our example code starts sorting by ` title ` . Try adding some posts and see them inserted in the correct sort
42
+ order.
43
+
44
+ <HooksPlayground fixtures ={postFixtures} getInitialInterceptorData ={getInitialInterceptorData} row >
45
+
46
+ ``` ts title="getPosts" {20-27}
47
+ import { Entity , RestEndpoint } from ' @data-client/rest' ;
48
+
49
+ class Post extends Entity {
50
50
id = ' ' ;
51
- name = ' ' ;
52
- isAdmin = false ;
51
+ title = ' ' ;
52
+ group = ' ' ;
53
+ author = ' ' ;
54
+
53
55
pk() {
54
56
return this .id ;
55
57
}
56
58
}
57
- export const UserResource = createResource ({
58
- path: ' /users/:id' ,
59
- schema: User ,
59
+ export const getPosts = new RestEndpoint ({
60
+ path: ' /:group/posts' ,
61
+ searchParams: {} as { orderBy? : string ; author? : string },
62
+ schema: new schema .Query (
63
+ new schema .Collection ([Post ], {
64
+ nonFilterArgumentKeys: / orderBy/ ,
65
+ }),
66
+ (posts , { orderBy } = {}) => {
67
+ if (orderBy && posts ) {
68
+ return [... posts ].sort ((a , b ) =>
69
+ a [orderBy ].localeCompare (b [orderBy ]),
70
+ );
71
+ }
72
+ return posts ;
73
+ },
74
+ ),
60
75
});
61
76
```
62
77
63
- ``` tsx title="UsersPage.tsx"
64
- import { schema } from ' @data-client/rest' ;
65
- import { useQuery , useFetch } from ' @data-client/react' ;
66
- import { UserResource , User } from ' ./api/User' ;
78
+ ``` tsx title="NewPost" collapsed
79
+ import { useLoading } from ' @data-client/hooks' ;
80
+ import { getPosts } from ' ./getPosts' ;
81
+
82
+ export default function NewPost({ user }: { user: string }) {
83
+ const ctrl = useController ();
84
+
85
+ const [handlePress, loading] = useLoading (async e => {
86
+ if (e .key === ' Enter' ) {
87
+ const title = e .currentTarget .value ;
88
+ e .currentTarget .value = ' ' ;
89
+ await ctrl .fetch (getPosts .push , {group: ' react' }, {
90
+ title ,
91
+ author: user ,
92
+ });
93
+ }
94
+ });
67
95
68
- interface Args {
69
- asc: boolean ;
70
- isAdmin? : boolean ;
96
+ return (
97
+ <div >
98
+ <input type = " text" onKeyDown = { handlePress } />{ loading ? ' ...' : ' ' }
99
+ </div >
100
+ );
71
101
}
72
- const sortedUsers = new schema .Query (
73
- new schema .All (User ),
74
- (entries , { asc , isAdmin }: Args = { asc: false }) => {
75
- let sorted = [... entries ].sort ((a , b ) => a .name .localeCompare (b .name ));
76
- if (isAdmin !== undefined )
77
- sorted = sorted .filter (user => user .isAdmin === isAdmin );
78
- if (asc ) return sorted ;
79
- return sorted .reverse ();
80
- },
81
- );
102
+ ```
82
103
83
- function UsersPage() {
84
- useFetch (UserResource .getList );
85
- const users = useQuery (sortedUsers , { asc: true });
86
- if (! users ) return <div >No users in cache yet</div >;
104
+ ``` tsx title="PostList" collapsed
105
+ import { useSuspense } from ' @data-client/react' ;
106
+ import { getPosts } from ' ./getPosts' ;
107
+ import NewPost from ' ./NewPost' ;
108
+
109
+ export default function PostList({
110
+ user ,
111
+ }) {
112
+ const posts = useSuspense (getPosts , { author: user , orderBy: ' title' , group: ' react' });
113
+ return (
114
+ <div >
115
+ { posts .map (post => (
116
+ <div key = { post .pk ()} >{ post .title } </div >
117
+ ))}
118
+ <NewPost user = { user } />
119
+ </div >
120
+ );
121
+ }
122
+ ```
123
+
124
+ ``` tsx title="UserList" collapsed
125
+ import PostList from ' ./PostList' ;
126
+
127
+ function UserList() {
128
+ const users = [' bob' , ' clara' ]
87
129
return (
88
130
<div >
89
131
{ users .map (user => (
90
- <div key = { user .pk ()} >{ user .name } </div >
132
+ <section key = { user } >
133
+ <h3 >{ user } </h3 >
134
+ <PostList user = { user } />
135
+ </section >
91
136
))}
92
137
</div >
93
138
);
94
139
}
95
- render (<UsersPage />);
140
+ render (<UserList />);
96
141
```
97
142
98
143
</HooksPlayground >
@@ -291,7 +336,10 @@ import { UserResource } from './api/User';
291
336
const groupTodoByUser = new schema .Query (
292
337
TodoResource .getList .schema ,
293
338
todos => {
294
- return Object .groupBy (todos , todo => todo ?.userId ?.username ) as Record <string , Todo []>;
339
+ return Object .groupBy (todos , todo => todo ?.userId ?.username ) as Record <
340
+ string ,
341
+ Todo []
342
+ >;
295
343
},
296
344
);
297
345
0 commit comments