Skip to content

Commit 8470660

Browse files
committed
docs: Add some examples to useController() page
1 parent f526931 commit 8470660

File tree

1 file changed

+109
-9
lines changed

1 file changed

+109
-9
lines changed

docs/core/api/useController.md

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,120 @@ function MyComponent({ id }) {
4949

5050
## Examples
5151

52-
### Using the resolution
52+
### Form submission
5353

54-
`controller.fetch()` matches the return type [useSuspense()](./useSuspense.md) - utilizing the [Endpoint.schema](/rest/api/RestEndpoint#schema)
55-
when possible. This allows us to use any class members.
54+
[fetch](./Controller.md#fetch) returns the denormalized response, matching [useSuspense()](./useSuspense.md)'s return type. This allows using Entity methods like `pk()`.
5655

57-
```ts
58-
import { useController } from '@data-client/react';
56+
```tsx
57+
function CreatePost() {
58+
const ctrl = useController();
5959

60-
const post = await controller.fetch(PostResource.getList.push, createPayload);
61-
post.title;
62-
post.computedField
63-
post.pk();
60+
const handleSubmit = async (e: FormEvent) => {
61+
e.preventDefault();
62+
const post = await ctrl.fetch(
63+
PostResource.getList.push,
64+
new FormData(e.target as HTMLFormElement),
65+
);
66+
post.title;
67+
post.computedField;
68+
navigate(`/post/${post.pk()}`);
69+
};
70+
71+
return <form onSubmit={handleSubmit}>{/* fields */}</form>;
72+
}
6473
```
6574

75+
### Direct entity update
76+
77+
Use [set](./Controller.md#set) for immediate updates without network requests. Supports functional updates to avoid race conditions.
78+
79+
```tsx
80+
function VoteButton({ articleId }: { articleId: string }) {
81+
const ctrl = useController();
82+
83+
return (
84+
<button
85+
onClick={() =>
86+
ctrl.set(Article, { id: articleId }, article => ({
87+
...article,
88+
votes: article.votes + 1,
89+
}))
90+
}
91+
>
92+
Vote
93+
</button>
94+
);
95+
}
96+
```
97+
98+
### Invalidate after mutation
99+
100+
Force refetch of related data using [invalidate](./Controller.md#invalidate) or [expireAll](./Controller.md#expireAll).
101+
102+
```tsx
103+
function ClearUserCache({ userId }: { userId: string }) {
104+
const ctrl = useController();
105+
106+
const handleClear = async () => {
107+
// invalidate() causes suspense; expireAll() refetches silently
108+
ctrl.expireAll(UserResource.get);
109+
ctrl.expireAll(UserResource.getList);
110+
};
111+
112+
return <button onClick={handleClear}>Refresh user data</button>;
113+
}
114+
```
115+
116+
:::tip
117+
118+
For better performance and consistency, prefer [including side effect updates in mutation responses](/rest/guides/side-effects).
119+
120+
:::
121+
122+
### Prefetching
123+
124+
Use [fetchIfStale](./Controller.md#fetchIfStale) to prefetch without overfetching fresh data.
125+
126+
```tsx
127+
function ArticleLink({ id }: { id: string }) {
128+
const ctrl = useController();
129+
130+
return (
131+
<Link
132+
to={`/article/${id}`}
133+
onMouseEnter={() => ctrl.fetchIfStale(ArticleResource.get, { id })}
134+
>
135+
Read more
136+
</Link>
137+
);
138+
}
139+
```
140+
141+
### Websocket updates
142+
143+
Populate cache with external data via [set](./Controller.md#set).
144+
145+
```tsx
146+
function useWebsocket(url: string) {
147+
const ctrl = useController();
148+
149+
useEffect(() => {
150+
const ws = new WebSocket(url);
151+
ws.onmessage = event => {
152+
const { entity, args, data } = JSON.parse(event.data);
153+
ctrl.set(EntityMap[entity], args, data);
154+
};
155+
return () => ws.close();
156+
}, [ctrl, url]);
157+
}
158+
```
159+
160+
:::warning
161+
162+
For production use, implement a [Manager for data streams](../concepts/managers.md#data-stream) rather than component-level effects. Managers handle connection lifecycle globally and work with SSR.
163+
164+
:::
165+
66166
### Todo App
67167

68168
<StackBlitz app="todo-app" file="src/resources/TodoResource.ts,src/pages/Home/TodoListItem.tsx" view="both" />

0 commit comments

Comments
 (0)