Skip to content

Commit 90c1429

Browse files
committed
docs: Start grouping endpoints the moment there is more than one in intro
1 parent 9d5c59a commit 90c1429

File tree

1 file changed

+59
-43
lines changed

1 file changed

+59
-43
lines changed

docs/core/README.md

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ prevents 'data tearing' jank and improves performance.
154154
import { Entity } from '@data-client/rest';
155155

156156
export class Todo extends Entity {
157-
userId = 0;
158157
id = 0;
158+
userId = 0;
159159
title = '';
160160
completed = false;
161161
}
@@ -166,7 +166,6 @@ import { GQLEntity } from '@data-client/graphql';
166166

167167
export class Todo extends GQLEntity {
168168
userId = 0;
169-
id = 0;
170169
title = '';
171170
completed = false;
172171
}
@@ -183,26 +182,28 @@ data integrity as well as TypeScript definitions.
183182

184183
<ProtocolTabs>
185184

186-
```ts {6,13}
185+
```ts {6}
187186
import { RestEndpoint } from '@data-client/rest';
188187

189-
export const getTodo = new RestEndpoint({
188+
const get = new RestEndpoint({
190189
urlPrefix: 'https://jsonplaceholder.typicode.com',
191190
path: '/todos/:id',
192191
schema: Todo,
193192
});
194193

195-
export const updateTodo = getTodo.extend({
194+
const update = getTodo.extend({
196195
method: 'PUT',
197196
});
197+
198+
export const TodoResource = { get, update };
198199
```
199200

200201
```ts {14,25}
201202
import { GQLEndpoint } from '@data-client/graphql';
202203

203204
const gql = new GQLEndpoint('/');
204205

205-
export const getTodo = gql.query(
206+
const get = gql.query(
206207
`query GetTodo($id: ID!) {
207208
todo(id: $id) {
208209
id
@@ -214,7 +215,7 @@ export const getTodo = gql.query(
214215
{ todo: Todo },
215216
);
216217

217-
export const updateTodo = gql.mutation(
218+
const update = gql.mutation(
218219
`mutation UpdateTodo($todo: Todo!) {
219220
updateTodo(todo: $todo) {
220221
id
@@ -224,6 +225,8 @@ export const updateTodo = gql.mutation(
224225
}`,
225226
{ updateTodo: Todo },
226227
);
228+
229+
export const TodoResource = { get, update };
227230
```
228231

229232
</ProtocolTabs>
@@ -237,17 +240,32 @@ Just like `setState()`, we must make React aware of the any mutations so it can
237240

238241
We can [useController](./api/useController.md) to access it in React components.
239242

243+
<ProtocolTabs>
244+
245+
```tsx
246+
import { useController } from '@data-client/react';
247+
248+
function ArticleEdit() {
249+
const ctrl = useController();
250+
// highlight-next-line
251+
const handleSubmit = data => ctrl.fetch(TodoResource.update, { id }, data);
252+
return <ArticleForm onSubmit={handleSubmit} />;
253+
}
254+
```
255+
240256
```tsx
241257
import { useController } from '@data-client/react';
242258

243259
function ArticleEdit() {
244260
const ctrl = useController();
245261
// highlight-next-line
246-
const handleSubmit = data => ctrl.fetch(updateTodo, { id }, data);
262+
const handleSubmit = data => ctrl.fetch(TodoResource.update, { id, ...data });
247263
return <ArticleForm onSubmit={handleSubmit} />;
248264
}
249265
```
250266

267+
</ProtocolTabs>
268+
251269
<details>
252270
<summary><b>Tracking imperative loading/error state</b></summary>
253271

@@ -260,45 +278,36 @@ function ArticleEdit() {
260278
const ctrl = useController();
261279
// highlight-next-line
262280
const [handleSubmit, loading, error] = useLoading(
263-
data => ctrl.fetch(updateTodo, { id }, data),
281+
data => ctrl.fetch(TodoResource.update, { id }, data),
264282
[ctrl],
265283
);
266284
return <ArticleForm onSubmit={handleSubmit} loading={loading} />;
267285
}
268286
```
269287

270-
React 18 version with [useTransition](https://react.dev/reference/react/useTransition)
271-
272-
```tsx
273-
import { useTransition } from 'react';
274-
import { useController } from '@data-client/react';
275-
276-
function ArticleEdit() {
277-
const ctrl = useController();
278-
const [loading, startTransition] = useTransition();
279-
const handleSubmit = data =>
280-
startTransition(() => ctrl.fetch(updateTodo, { id }, data));
281-
return <ArticleForm onSubmit={handleSubmit} loading={loading} />;
282-
}
283-
```
284-
285288
</details>
286289

287290
### More data modeling
288291

289-
What if our entity is not the top level item? Here we define the `todoList`
290-
endpoint with `[Todo]` as its schema. [Schemas](./concepts/normalization.md#schema) tell Reactive Data Client _where_ to find
292+
What if our entity is not the top level item? Here we define the `getList`
293+
endpoint with [new schema.Collection([Todo])](/rest/api/Collection) as its schema. [Schemas](./concepts/normalization.md#schema) tell Reactive Data Client _where_ to find
291294
the Entities. By placing inside a list, Reactive Data Client knows to expect a response
292295
where each item of the list is the entity specified.
293296

294297
```typescript {6}
295298
import { RestEndpoint, schema } from '@data-client/rest';
296299

297-
export const getTodoList = new RestEndpoint({
300+
// get and update definitions omitted
301+
302+
const getList = new RestEndpoint({
298303
urlPrefix: 'https://jsonplaceholder.typicode.com',
299304
path: '/todos',
300305
schema: new schema.Collection([Todo]),
306+
searchParams: {} as { userId?: string | number } | undefined,
307+
paginationField: 'page',
301308
});
309+
310+
export default TodoResource = { getList, get, update };
302311
```
303312

304313
[Schemas](./concepts/normalization.md) also automatically infer and enforce the response type, ensuring
@@ -308,7 +317,7 @@ the variable `todos` will be typed precisely.
308317
import { useSuspense } from '@data-client/react';
309318

310319
export default function TodoList() {
311-
const todos = useSuspense(getTodoList);
320+
const todos = useSuspense(TodoResource.getList);
312321

313322
return (
314323
<div>
@@ -320,12 +329,12 @@ export default function TodoList() {
320329
}
321330
```
322331

323-
Now we've used our data model in three cases - `getTodo`, `getTodoList` and `updateTodo`. Data consistency
332+
Now we've used our data model in three cases - `TodoResource.get`, `TodoResource.getList` and `TodoResource.update`. Data consistency
324333
(as well as referential equality) will be guaranteed between the endpoints, even after mutations occur.
325334

326335
### Organizing Endpoints
327336

328-
At this point we've defined `todoDetail`, `todoList` and `todoUpdate`. You might have noticed
337+
At this point we've defined `TodoResource.get`, `TodoResource.getList` and `TodoResource.update`. You might have noticed
329338
that these endpoint definitions share some logic and information. For this reason Reactive Data Client
330339
encourages extracting shared logic among endpoints.
331340

@@ -345,10 +354,12 @@ const TodoResource = resource({
345354
urlPrefix: 'https://jsonplaceholder.typicode.com',
346355
path: '/todos/:id',
347356
schema: Todo,
357+
searchParams: {} as { userId?: string | number } | undefined,
358+
paginationField: 'page',
348359
});
349360
```
350361

351-
[Introduction to Resource](/rest)
362+
[Introduction to Resource](./getting-started/resource.md)
352363

353364
<details>
354365
<summary><b>Resource Endpoints</b></summary>
@@ -361,12 +372,21 @@ const todo = useSuspense(TodoResource.get, { id: 5 });
361372
// GET https://jsonplaceholder.typicode.com/todos
362373
const todos = useSuspense(TodoResource.getList);
363374

375+
// GET https://jsonplaceholder.typicode.com/todos?userId=1
376+
const todos = useSuspense(TodoResource.getList, { userId: 1 });
377+
364378
// mutate
365379
const ctrl = useController();
366380

381+
// GET https://jsonplaceholder.typicode.com/todos?userId=1
382+
ctrl.fetch(TodoResource.getList.getPage, { userId: 1, page: 2 });
383+
367384
// POST https://jsonplaceholder.typicode.com/todos
368385
ctrl.fetch(TodoResource.getList.push, { title: 'my todo' });
369386

387+
// POST https://jsonplaceholder.typicode.com/todos?userId=1
388+
ctrl.fetch(TodoResource.getList.push, { userId: 1 }, { title: 'my todo' });
389+
370390
// PUT https://jsonplaceholder.typicode.com/todos/5
371391
ctrl.fetch(TodoResource.update, { id: 5 }, { title: 'my todo' });
372392

@@ -395,7 +415,7 @@ we'll need to specify _how_.
395415
value, as well as the fetch arguments, we return the _expected_ fetch response.
396416

397417
```typescript
398-
export const updateTodo = new RestEndpoint({
418+
const update = new RestEndpoint({
399419
urlPrefix: 'https://jsonplaceholder.typicode.com',
400420
path: '/todos/:id',
401421
method: 'PUT',
@@ -428,32 +448,28 @@ which can be used to [initiate data updates](./concepts/managers.md#data-stream)
428448
<summary><b>StreamManager</b></summary>
429449

430450
```typescript
431-
import type { Manager, Middleware } from '@data-client/core';
432-
import type { EndpointInterface } from '@data-client/endpoint';
451+
import type { Manager, Middleware, ActionTypes } from '@data-client/react';
452+
import { Controller, actionTypes } from '@data-client/react';
453+
import type { EntityInterface } from '@data-client/rest';
433454

434455
export default class StreamManager implements Manager {
435-
protected declare middleware: Middleware;
436456
protected declare evtSource: WebSocket | EventSource;
437-
protected declare endpoints: Record<string, EndpointInterface>;
457+
protected declare entities: Record<string, typeof EntityInterface>;
438458

439459
constructor(
440460
evtSource: WebSocket | EventSource,
441-
endpoints: Record<string, EndpointInterface>,
461+
entities: Record<string, EntityInterface>,
442462
) {
443463
this.evtSource = evtSource;
444-
this.endpoints = endpoints;
464+
this.entities = entities;
445465
}
446466

447467
middleware: Middleware = controller => {
448468
this.evtSource.onmessage = event => {
449469
try {
450470
const msg = JSON.parse(event.data);
451471
if (msg.type in this.endpoints)
452-
controller.setResponse(
453-
this.endpoints[msg.type],
454-
...msg.args,
455-
msg.data,
456-
);
472+
controller.set(this.entities[msg.type], ...msg.args, msg.data);
457473
} catch (e) {
458474
console.error('Failed to handle message');
459475
console.error(e);

0 commit comments

Comments
 (0)