File size: 76,414 Bytes
9375fc1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
<!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>docs/api/hooks/async-hooks | react-declarative</title><meta name="description" content="Documentation for react-declarative"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">react-declarative</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">react-declarative</a></li><li><a href="docs_api_hooks_async-hooks.html">docs/api/hooks/async-hooks</a></li></ul></div><div class="tsd-panel tsd-typography"><a id="async-hooks-usesinglerunaction-usequeuedaction-and-more" class="tsd-anchor"></a><h1 class="tsd-anchor-link">Async hooks: useSinglerunAction, useQueuedAction, and more<a href="#async-hooks-usesinglerunaction-usequeuedaction-and-more" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h1><p>Async hooks give you a consistent way to handle asynchronous operations in your components. Each hook returns a <code>loading</code> boolean and an <code>error</code> boolean alongside an <code>execute</code> function, so you can drive UI state without writing boilerplate. Depending on which hook you choose, you get additional behavior: single-execution guards, ordered queuing, batch progress tracking, or a shared semaphore that disables multiple buttons at once.</p>
<a id="usesinglerunaction" class="tsd-anchor"></a><h2 class="tsd-anchor-link">useSinglerunAction<a href="#usesinglerunaction" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Wraps an async function so that <strong>only one invocation can run at a time</strong>. If you call <code>execute</code> while a previous call is still pending, the new call is a no-op until the first one settles. This is useful for upload buttons and any action where duplicate submissions would cause problems.</p>
<a id="signature" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Signature<a href="#signature" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="ts"><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">useSinglerunAction</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">, </span><span class="hl-7">Payload</span><span class="hl-1">&gt;(</span><br/><span class="hl-1">  </span><span class="hl-5">run</span><span class="hl-1">: (</span><span class="hl-2">payload</span><span class="hl-1">: </span><span class="hl-7">Payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;,</span><br/><span class="hl-1">  </span><span class="hl-2">options</span><span class="hl-1">?: {</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadStart</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">fallback</span><span class="hl-1">?: (</span><span class="hl-2">e</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-2">throwError</span><span class="hl-1">?: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  }</span><br/><span class="hl-1">): {</span><br/><span class="hl-1">  </span><span class="hl-5">execute</span><span class="hl-1">: (</span><span class="hl-2">payload</span><span class="hl-1">?: </span><span class="hl-7">Payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">null</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">  </span><span class="hl-2">loading</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<a id="parameters" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Parameters<a href="#parameters" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><strong><code>run</code></strong> <em>(required)</em><code>(payload: Payload) =&gt; Data | Promise&lt;Data&gt;</code></p>
<p>The async function to execute. Receives an optional <code>payload</code> argument and must return the result or a Promise of the result.</p>
<p><strong><code>options.onLoadStart</code></strong><code>() =&gt; void</code></p>
<p>Called immediately before the action begins executing. Use this to show a global loader.</p>
<p><strong><code>options.onLoadEnd</code></strong><code>(isOk: boolean) =&gt; void</code></p>
<p>Called after the action completes or fails. <code>isOk</code> is <code>false</code> when an error was thrown.</p>
<p><strong><code>options.fallback</code></strong><code>(e: Error) =&gt; void</code></p>
<p>Called with the caught error when the action throws and <code>throwError</code> is <code>false</code> (the default). Use this to display an error toast.</p>
<p><strong><code>options.throwError</code></strong><code>boolean</code> <em>(default: <code>false</code>)</em></p>
<p>When <code>true</code>, errors thrown inside <code>run</code> are re-thrown from <code>execute</code> instead of being passed to <code>fallback</code>.</p>
<a id="return-value" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Return value<a href="#return-value" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>execute</code></td>
<td><code>(payload?) =&gt; Promise&lt;Data | null&gt;</code></td>
<td>Triggers the action. Concurrent calls while loading are silently dropped. Call <code>execute.clear()</code> to reset the single-run lock.</td>
</tr>
<tr>
<td><code>loading</code></td>
<td><code>boolean</code></td>
<td><code>true</code> while the action is running.</td>
</tr>
<tr>
<td><code>error</code></td>
<td><code>boolean</code></td>
<td><code>true</code> if the most recent invocation threw an error.</td>
</tr>
</tbody>
</table>
<a id="usage" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Usage<a href="#usage" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useSinglerunAction</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">UploadButton</span><span class="hl-1">({ </span><span class="hl-2">onChange</span><span class="hl-1"> }: { </span><span class="hl-5">onChange</span><span class="hl-1">: (</span><span class="hl-2">path</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1"> }) {</span><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-10">execute</span><span class="hl-1">, </span><span class="hl-10">loading</span><span class="hl-1"> } = </span><span class="hl-5">useSinglerunAction</span><span class="hl-1">(</span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">file</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-5">chooseFile</span><span class="hl-1">(</span><span class="hl-3">&#39;image/jpeg,image/png&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">file</span><span class="hl-1">) {</span><br/><span class="hl-1">      </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">filePath</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">uploadService</span><span class="hl-1">.</span><span class="hl-5">upload</span><span class="hl-1">(</span><span class="hl-2">file</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-5">onChange</span><span class="hl-1">(</span><span class="hl-2">filePath</span><span class="hl-1">);</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">  });</span><br/><br/><span class="hl-1">  </span><span class="hl-0">return</span><span class="hl-1"> (</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;</span><span class="hl-18">button</span><span class="hl-1"> </span><span class="hl-8">onClick</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">execute</span><span class="hl-4">}</span><span class="hl-1"> </span><span class="hl-8">disabled</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-4">}</span><span class="hl-6">&gt;</span><br/><span class="hl-1">      </span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-9"> </span><span class="hl-1">?</span><span class="hl-9"> </span><span class="hl-3">&#39;Uploading…&#39;</span><span class="hl-9"> </span><span class="hl-1">:</span><span class="hl-9"> </span><span class="hl-3">&#39;Upload image&#39;</span><span class="hl-4">}</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;/</span><span class="hl-18">button</span><span class="hl-6">&gt;</span><br/><span class="hl-1">  );</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<hr>
<a id="usequeuedaction" class="tsd-anchor"></a><h2 class="tsd-anchor-link">useQueuedAction<a href="#usequeuedaction" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Runs every call in the order it was received — earlier calls must complete before later ones start. Unlike <code>useSinglerunAction</code>, <strong>no calls are dropped</strong>: they queue up and execute sequentially. This is ideal for real-time state-reducer patterns such as processing WebSocket events in order.</p>
<a id="signature-1" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Signature<a href="#signature-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="ts"><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">useQueuedAction</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">, </span><span class="hl-7">Payload</span><span class="hl-1">&gt;(</span><br/><span class="hl-1">  </span><span class="hl-5">run</span><span class="hl-1">: (</span><span class="hl-2">payload</span><span class="hl-1">: </span><span class="hl-7">Payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;,</span><br/><span class="hl-1">  </span><span class="hl-2">options</span><span class="hl-1">?: {</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadStart</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">fallback</span><span class="hl-1">?: (</span><span class="hl-2">e</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-2">throwError</span><span class="hl-1">?: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  }</span><br/><span class="hl-1">): {</span><br/><span class="hl-1">  </span><span class="hl-5">execute</span><span class="hl-1">: (</span><span class="hl-2">payload</span><span class="hl-1">?: </span><span class="hl-7">Payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">null</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">  </span><span class="hl-2">loading</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<a id="parameters-1" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Parameters<a href="#parameters-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><strong><code>run</code></strong> <em>(required)</em><code>(payload: Payload) =&gt; Data | Promise&lt;Data&gt;</code></p>
<p>The async function to execute for each queued item.</p>
<p><strong><code>options.onLoadStart</code></strong><code>() =&gt; void</code></p>
<p>Called before each queued execution begins.</p>
<p><strong><code>options.onLoadEnd</code></strong><code>(isOk: boolean) =&gt; void</code></p>
<p>Called after each queued execution completes or fails.</p>
<p><strong><code>options.fallback</code></strong><code>(e: Error) =&gt; void</code></p>
<p>Error handler when <code>throwError</code> is <code>false</code>.</p>
<p><strong><code>options.throwError</code></strong><code>boolean</code> <em>(default: <code>false</code>)</em></p>
<p>Re-throws errors from <code>execute</code> instead of routing them to <code>fallback</code>.</p>
<a id="return-value-1" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Return value<a href="#return-value-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>execute</code></td>
<td><code>(payload?) =&gt; Promise&lt;Data | null&gt;</code></td>
<td>Enqueues a call. Call <code>execute.cancel()</code> to abandon the current item and <code>execute.clear()</code> to drain the entire queue.</td>
</tr>
<tr>
<td><code>loading</code></td>
<td><code>boolean</code></td>
<td><code>true</code> while any item is being processed.</td>
</tr>
<tr>
<td><code>error</code></td>
<td><code>boolean</code></td>
<td><code>true</code> if the most recent item threw.</td>
</tr>
</tbody>
</table>
<a id="usage-1" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Usage<a href="#usage-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useEffect</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useQueuedAction</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">KanbanBoard</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-10">execute</span><span class="hl-1"> } = </span><span class="hl-5">useQueuedAction</span><span class="hl-1">(</span><br/><span class="hl-1">    </span><span class="hl-4">async</span><span class="hl-1"> ({ </span><span class="hl-2">type</span><span class="hl-1">, </span><span class="hl-2">payload</span><span class="hl-1"> }) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">      </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">type</span><span class="hl-1"> === </span><span class="hl-3">&#39;create&#39;</span><span class="hl-1">) </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">createCard</span><span class="hl-1">(</span><span class="hl-2">payload</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">type</span><span class="hl-1"> === </span><span class="hl-3">&#39;update&#39;</span><span class="hl-1">) </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">updateCard</span><span class="hl-1">(</span><span class="hl-2">payload</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">type</span><span class="hl-1"> === </span><span class="hl-3">&#39;remove&#39;</span><span class="hl-1">) </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">removeCard</span><span class="hl-1">(</span><span class="hl-2">payload</span><span class="hl-1">);</span><br/><span class="hl-1">    },</span><br/><span class="hl-1">    {</span><br/><span class="hl-1">      </span><span class="hl-5">onLoadStart</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-5">setAppbarLoader</span><span class="hl-1">(</span><span class="hl-4">true</span><span class="hl-1">),</span><br/><span class="hl-1">      </span><span class="hl-5">onLoadEnd</span><span class="hl-2">:</span><span class="hl-1">   () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-5">setAppbarLoader</span><span class="hl-1">(</span><span class="hl-4">false</span><span class="hl-1">),</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">  );</span><br/><br/><span class="hl-1">  </span><span class="hl-5">useEffect</span><span class="hl-1">(() </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">kanbanService</span><span class="hl-1">.</span><span class="hl-2">createSubject</span><span class="hl-1">.</span><span class="hl-5">subscribe</span><span class="hl-1">(</span><span class="hl-2">execute</span><span class="hl-1">), []);</span><br/><span class="hl-1">  </span><span class="hl-5">useEffect</span><span class="hl-1">(() </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">kanbanService</span><span class="hl-1">.</span><span class="hl-2">updateSubject</span><span class="hl-1">.</span><span class="hl-5">subscribe</span><span class="hl-1">(</span><span class="hl-2">execute</span><span class="hl-1">), []);</span><br/><span class="hl-1">  </span><span class="hl-5">useEffect</span><span class="hl-1">(() </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">kanbanService</span><span class="hl-1">.</span><span class="hl-2">removeSubject</span><span class="hl-1">.</span><span class="hl-5">subscribe</span><span class="hl-1">(</span><span class="hl-2">execute</span><span class="hl-1">), []);</span><br/><br/><span class="hl-1">  </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-6">&lt;</span><span class="hl-7">Board</span><span class="hl-1"> </span><span class="hl-6">/&gt;</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<hr>
<a id="useasyncaction" class="tsd-anchor"></a><h2 class="tsd-anchor-link">useAsyncAction<a href="#useasyncaction" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The foundational async hook. Every call to <code>execute</code> <strong>cancels the previous in-flight call</strong> and starts a fresh one. Use this when you want the latest request to always win — for example, live search or on-demand data loads triggered by user interactions.</p>
<a id="signature-2" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Signature<a href="#signature-2" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="ts"><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">useAsyncAction</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">, </span><span class="hl-7">Payload</span><span class="hl-1">&gt;(</span><br/><span class="hl-1">  </span><span class="hl-5">run</span><span class="hl-1">: (</span><span class="hl-2">payload</span><span class="hl-1">: </span><span class="hl-7">Payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;,</span><br/><span class="hl-1">  </span><span class="hl-2">options</span><span class="hl-1">?: {</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadStart</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">fallback</span><span class="hl-1">?: (</span><span class="hl-2">e</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-2">throwError</span><span class="hl-1">?: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  }</span><br/><span class="hl-1">): {</span><br/><span class="hl-1">  </span><span class="hl-5">execute</span><span class="hl-1">: (</span><span class="hl-2">payload</span><span class="hl-1">?: </span><span class="hl-7">Payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">null</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">  </span><span class="hl-2">loading</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<a id="parameters-2" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Parameters<a href="#parameters-2" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><strong><code>run</code></strong> <em>(required)</em><code>(payload: Payload) =&gt; Data | Promise&lt;Data&gt;</code></p>
<p>The async function to run. The previous invocation is cancelled when a new <code>execute</code> call arrives.</p>
<p><strong><code>options.onLoadStart</code></strong><code>() =&gt; void</code></p>
<p>Called before each execution.</p>
<p><strong><code>options.onLoadEnd</code></strong><code>(isOk: boolean) =&gt; void</code></p>
<p>Called after each execution.</p>
<p><strong><code>options.fallback</code></strong><code>(e: Error) =&gt; void</code></p>
<p>Error handler when <code>throwError</code> is <code>false</code>.</p>
<p><strong><code>options.throwError</code></strong><code>boolean</code> <em>(default: <code>false</code>)</em></p>
<p>Re-throws errors from <code>execute</code>.</p>
<a id="return-value-2" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Return value<a href="#return-value-2" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>execute</code></td>
<td><code>(payload?) =&gt; Promise&lt;Data | null&gt;</code></td>
<td>Triggers the action, cancelling any previous pending call.</td>
</tr>
<tr>
<td><code>loading</code></td>
<td><code>boolean</code></td>
<td><code>true</code> while the current call is running.</td>
</tr>
<tr>
<td><code>error</code></td>
<td><code>boolean</code></td>
<td><code>true</code> if the most recent call threw.</td>
</tr>
</tbody>
</table>
<a id="usage-2" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Usage<a href="#usage-2" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useAsyncAction</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">SaveButton</span><span class="hl-1">({ </span><span class="hl-2">data</span><span class="hl-1"> }: { </span><span class="hl-2">data</span><span class="hl-1">: </span><span class="hl-7">FormData</span><span class="hl-1"> }) {</span><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-10">execute</span><span class="hl-1">, </span><span class="hl-10">loading</span><span class="hl-1">, </span><span class="hl-10">error</span><span class="hl-1"> } = </span><span class="hl-5">useAsyncAction</span><span class="hl-1">(</span><br/><span class="hl-1">    </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-2">formData</span><span class="hl-1">: </span><span class="hl-7">FormData</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">      </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">save</span><span class="hl-1">(</span><span class="hl-2">formData</span><span class="hl-1">);</span><br/><span class="hl-1">    },</span><br/><span class="hl-1">    {</span><br/><span class="hl-1">      </span><span class="hl-5">fallback</span><span class="hl-2">:</span><span class="hl-1"> (</span><span class="hl-2">e</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">toast</span><span class="hl-1">.</span><span class="hl-5">error</span><span class="hl-1">(</span><span class="hl-2">e</span><span class="hl-1">.</span><span class="hl-2">message</span><span class="hl-1">),</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">  );</span><br/><br/><span class="hl-1">  </span><span class="hl-0">return</span><span class="hl-1"> (</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;&gt;</span><br/><span class="hl-1">      </span><span class="hl-4">{</span><span class="hl-2">error</span><span class="hl-9"> </span><span class="hl-1">&amp;&amp;</span><span class="hl-9"> </span><span class="hl-6">&lt;</span><span class="hl-18">span</span><span class="hl-6">&gt;</span><span class="hl-9">Save failed — please try again.</span><span class="hl-6">&lt;/</span><span class="hl-18">span</span><span class="hl-6">&gt;</span><span class="hl-4">}</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;</span><span class="hl-18">button</span><span class="hl-1"> </span><span class="hl-8">onClick</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">() </span><span class="hl-4">=&gt;</span><span class="hl-9"> </span><span class="hl-5">execute</span><span class="hl-9">(</span><span class="hl-2">data</span><span class="hl-9">)</span><span class="hl-4">}</span><span class="hl-1"> </span><span class="hl-8">disabled</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-4">}</span><span class="hl-6">&gt;</span><br/><span class="hl-1">        Save</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;/</span><span class="hl-18">button</span><span class="hl-6">&gt;</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;/&gt;</span><br/><span class="hl-1">  );</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<hr>
<a id="useasyncprogress" class="tsd-anchor"></a><h2 class="tsd-anchor-link">useAsyncProgress<a href="#useasyncprogress" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Processes a <strong>batch of items sequentially</strong> while tracking progress as a percentage (0–100). Each item in the array is processed one at a time; the hook exposes the current progress value and any per-item errors that accumulated. Feed the <code>progress</code> value directly into a <code>&lt;LinearProgress /&gt;</code> component.</p>
<a id="signature-3" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Signature<a href="#signature-3" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="ts"><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-7">IProcess</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt; {</span><br/><span class="hl-1">  </span><span class="hl-2">label</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">;  </span><span class="hl-17">// human-readable identifier shown while processing</span><br/><span class="hl-1">  </span><span class="hl-2">data</span><span class="hl-1">: </span><span class="hl-7">Data</span><span class="hl-1">;     </span><span class="hl-17">// the payload passed to your process function</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">useAsyncProgress</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">, </span><span class="hl-7">Result</span><span class="hl-1"> = </span><span class="hl-7">void</span><span class="hl-1">&gt;(</span><br/><span class="hl-1">  </span><span class="hl-5">process</span><span class="hl-1">: (</span><span class="hl-2">item</span><span class="hl-1">: </span><span class="hl-7">IProcess</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Result</span><span class="hl-1"> | </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Result</span><span class="hl-1">&gt;,</span><br/><span class="hl-1">  </span><span class="hl-2">options</span><span class="hl-1">?: {</span><br/><span class="hl-1">    </span><span class="hl-2">delay</span><span class="hl-1">?: </span><span class="hl-7">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onBegin</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onFinish</span><span class="hl-1">?: (</span><br/><span class="hl-1">      </span><span class="hl-2">data</span><span class="hl-1">: </span><span class="hl-7">Data</span><span class="hl-1">[],</span><br/><span class="hl-1">      </span><span class="hl-2">errors</span><span class="hl-1">: { </span><span class="hl-2">label</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">; </span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">; </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1"> }[],</span><br/><span class="hl-1">      </span><span class="hl-2">results</span><span class="hl-1">: (</span><span class="hl-7">Result</span><span class="hl-1"> | </span><span class="hl-7">null</span><span class="hl-1">)[]</span><br/><span class="hl-1">    ) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onError</span><span class="hl-1">?: (</span><span class="hl-2">errors</span><span class="hl-1">: { </span><span class="hl-2">label</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">; </span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">; </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1"> }[]) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1"> | </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onProgress</span><span class="hl-1">?: (</span><span class="hl-2">progress</span><span class="hl-1">: </span><span class="hl-7">number</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadStart</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">  }</span><br/><span class="hl-1">): {</span><br/><span class="hl-1">  </span><span class="hl-5">execute</span><span class="hl-1">: (</span><span class="hl-2">items</span><span class="hl-1">: </span><span class="hl-7">IProcess</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;[]) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">loading</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">progress</span><span class="hl-1">: </span><span class="hl-7">number</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">errors</span><span class="hl-1">: { </span><span class="hl-2">label</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">; </span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">; </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1"> }[];</span><br/><span class="hl-1">  </span><span class="hl-2">label</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<a id="parameters-3" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Parameters<a href="#parameters-3" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><strong><code>process</code></strong> <em>(required)</em><code>(item: { label: string; data: Data }) =&gt; Result | Promise&lt;Result&gt;</code></p>
<p>Called once per item. Each item has a human-readable <code>label</code> (used in error reporting) and the <code>data</code> object to process.</p>
<p><strong><code>options.delay</code></strong><code>number</code> <em>(default: <code>0</code>)</em></p>
<p>Minimum delay in milliseconds to hold on each item before advancing. Useful for giving the UI time to render progress updates.</p>
<p><strong><code>options.onBegin</code></strong><code>() =&gt; void</code></p>
<p>Called once before the first item is processed.</p>
<p><strong><code>options.onEnd</code></strong><code>(isOk: boolean) =&gt; void</code></p>
<p>Called once after all items are processed (or after an early abort). <code>isOk</code> is <code>false</code> if any item errored.</p>
<p><strong><code>options.onFinish</code></strong><code>(data, errors, results) =&gt; void</code></p>
<p>Called with the full input data array, all accumulated errors, and the result array after processing finishes.</p>
<p><strong><code>options.onError</code></strong><code>(errors) =&gt; void | boolean</code></p>
<p>Called when an item throws. Return <code>false</code> to abort the remaining items; return <code>true</code> or <code>undefined</code> to continue processing.</p>
<p><strong><code>options.onProgress</code></strong><code>(progress: number) =&gt; void</code></p>
<p>Called after each item with the updated percentage (0–100).</p>
<a id="return-value-3" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Return value<a href="#return-value-3" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>execute</code></td>
<td><code>(items: IProcess&lt;Data&gt;[]) =&gt; void</code></td>
<td>Starts processing the batch. Concurrent calls are blocked (single-run semantics).</td>
</tr>
<tr>
<td><code>loading</code></td>
<td><code>boolean</code></td>
<td><code>true</code> while the batch is running.</td>
</tr>
<tr>
<td><code>progress</code></td>
<td><code>number</code></td>
<td>Current percentage, 0–100.</td>
</tr>
<tr>
<td><code>errors</code></td>
<td><code>array</code></td>
<td>Items that threw, each with <code>label</code>, <code>message</code>, and <code>error</code>.</td>
</tr>
<tr>
<td><code>label</code></td>
<td><code>string</code></td>
<td>The <code>label</code> of the item currently being processed.</td>
</tr>
</tbody>
</table>
<a id="usage-3" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Usage<a href="#usage-3" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useState</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useAsyncProgress</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">LinearProgress</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;@mui/material/LinearProgress&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">ImportContacts</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> [</span><span class="hl-10">progress</span><span class="hl-1">, </span><span class="hl-10">setProgress</span><span class="hl-1">] = </span><span class="hl-5">useState</span><span class="hl-1">(</span><span class="hl-16">0</span><span class="hl-1">);</span><br/><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-10">execute</span><span class="hl-1">, </span><span class="hl-10">loading</span><span class="hl-1"> } = </span><span class="hl-5">useAsyncProgress</span><span class="hl-1">(</span><br/><span class="hl-1">    </span><span class="hl-4">async</span><span class="hl-1"> ({ </span><span class="hl-2">data</span><span class="hl-1"> }) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">      </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">createContact</span><span class="hl-1">(</span><span class="hl-2">data</span><span class="hl-1">);</span><br/><span class="hl-1">    },</span><br/><span class="hl-1">    {</span><br/><span class="hl-1">      </span><span class="hl-2">onProgress:</span><span class="hl-1"> </span><span class="hl-2">setProgress</span><span class="hl-1">,</span><br/><span class="hl-1">      </span><span class="hl-5">onError</span><span class="hl-2">:</span><span class="hl-1"> (</span><span class="hl-2">errors</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">        </span><span class="hl-2">console</span><span class="hl-1">.</span><span class="hl-5">error</span><span class="hl-1">(</span><span class="hl-3">&#39;Some rows failed:&#39;</span><span class="hl-1">, </span><span class="hl-2">errors</span><span class="hl-1">);</span><br/><span class="hl-1">        </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-4">true</span><span class="hl-1">; </span><span class="hl-17">// continue remaining rows</span><br/><span class="hl-1">      },</span><br/><span class="hl-1">      </span><span class="hl-5">onEnd</span><span class="hl-2">:</span><span class="hl-1"> (</span><span class="hl-2">isOk</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-5">navigate</span><span class="hl-1">(</span><span class="hl-2">isOk</span><span class="hl-1"> ? </span><span class="hl-3">&#39;/success&#39;</span><span class="hl-1"> : </span><span class="hl-3">&#39;/report&#39;</span><span class="hl-1">),</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">  );</span><br/><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">handleFileSelect</span><span class="hl-1"> = </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">file</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-5">chooseFile</span><span class="hl-1">(</span><span class="hl-3">&#39;.xlsx&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">file</span><span class="hl-1">) {</span><br/><span class="hl-1">      </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">rows</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-5">parseExcel</span><span class="hl-1">(</span><span class="hl-2">file</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-5">execute</span><span class="hl-1">(</span><span class="hl-2">rows</span><span class="hl-1">.</span><span class="hl-5">map</span><span class="hl-1">((</span><span class="hl-2">row</span><span class="hl-1">, </span><span class="hl-2">i</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({ </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">`Row </span><span class="hl-4">${</span><span class="hl-2">i</span><span class="hl-9"> </span><span class="hl-1">+</span><span class="hl-9"> </span><span class="hl-16">1</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">data:</span><span class="hl-1"> </span><span class="hl-2">row</span><span class="hl-1"> })));</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">  };</span><br/><br/><span class="hl-1">  </span><span class="hl-0">return</span><span class="hl-1"> (</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;&gt;</span><br/><span class="hl-1">      </span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-9"> </span><span class="hl-1">&amp;&amp;</span><span class="hl-9"> </span><span class="hl-6">&lt;</span><span class="hl-7">LinearProgress</span><span class="hl-9"> </span><span class="hl-8">variant</span><span class="hl-1">=</span><span class="hl-3">&quot;determinate&quot;</span><span class="hl-9"> </span><span class="hl-8">value</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">progress</span><span class="hl-4">}</span><span class="hl-9"> </span><span class="hl-6">/&gt;</span><span class="hl-4">}</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;</span><span class="hl-18">button</span><span class="hl-1"> </span><span class="hl-8">onClick</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">handleFileSelect</span><span class="hl-4">}</span><span class="hl-1"> </span><span class="hl-8">disabled</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-4">}</span><span class="hl-6">&gt;</span><br/><span class="hl-1">        Import XLSX</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;/</span><span class="hl-18">button</span><span class="hl-6">&gt;</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;/&gt;</span><br/><span class="hl-1">  );</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<hr>
<a id="useasyncvalue" class="tsd-anchor"></a><h2 class="tsd-anchor-link">useAsyncValue<a href="#useasyncvalue" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Fetches data asynchronously on mount (and whenever <code>deps</code> change) and stores the result in local state. It returns the current value, an action object for manual re-fetching, a setter for optimistic updates, and utility helpers. Think of it as <code>useState</code> combined with <code>useEffect</code> for async data.</p>
<a id="signature-4" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Signature<a href="#signature-4" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="ts"><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">useAsyncValue</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;(</span><br/><span class="hl-1">  </span><span class="hl-5">run</span><span class="hl-1">: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;,</span><br/><span class="hl-1">  </span><span class="hl-2">options</span><span class="hl-1">?: {</span><br/><span class="hl-1">    </span><span class="hl-2">deps</span><span class="hl-1">?: </span><span class="hl-7">any</span><span class="hl-1">[];</span><br/><span class="hl-1">    </span><span class="hl-5">fallback</span><span class="hl-1">?: (</span><span class="hl-2">e</span><span class="hl-1">: </span><span class="hl-7">Error</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadStart</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-5">onLoadEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-2">throwError</span><span class="hl-1">?: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  }</span><br/><span class="hl-1">): [</span><br/><span class="hl-1">  </span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">null</span><span class="hl-1">,                                                        </span><span class="hl-17">// [0] current value</span><br/><span class="hl-1">  { </span><span class="hl-5">execute</span><span class="hl-1">: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">void</span><span class="hl-1">&gt;; </span><span class="hl-2">loading</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">; </span><span class="hl-2">error</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1"> }, </span><span class="hl-17">// [1] action controls</span><br/><span class="hl-1">  (</span><span class="hl-2">data</span><span class="hl-1">: </span><span class="hl-7">Data</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">,                                               </span><span class="hl-17">// [2] optimistic setter</span><br/><span class="hl-1">  { </span><span class="hl-5">waitForResult</span><span class="hl-1">: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">Promise</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1">&gt;; </span><span class="hl-2">data$</span><span class="hl-1">: </span><span class="hl-7">MutableRefObject</span><span class="hl-1">&lt;</span><span class="hl-7">Data</span><span class="hl-1"> | </span><span class="hl-7">null</span><span class="hl-1">&gt; } </span><span class="hl-17">// [3] utilities</span><br/><span class="hl-1">]</span>
</code><button type="button">Copy</button></pre>

<a id="parameters-4" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Parameters<a href="#parameters-4" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><strong><code>run</code></strong> <em>(required)</em><code>() =&gt; Data | Promise&lt;Data&gt;</code></p>
<p>Factory function called on mount and whenever <code>deps</code> change. Takes no arguments; close over variables you need.</p>
<p><strong><code>options.deps</code></strong><code>any[]</code> <em>(default: <code>[]</code>)</em></p>
<p>Dependency array passed to the internal <code>useEffect</code>. When any dep changes, <code>run</code> is called again.</p>
<p><strong><code>options.fallback</code></strong><code>(e: Error) =&gt; void</code></p>
<p>Error handler when <code>throwError</code> is <code>false</code>.</p>
<p><strong><code>options.onLoadStart</code></strong><code>() =&gt; void</code></p>
<p>Called before each fetch.</p>
<p><strong><code>options.onLoadEnd</code></strong><code>(isOk: boolean) =&gt; void</code></p>
<p>Called after each fetch.</p>
<a id="return-value-4" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Return value<a href="#return-value-4" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
<thead>
<tr>
<th>Index</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>[0]</code></td>
<td><code>Data | null</code></td>
<td>The current fetched value, or <code>null</code> before the first load.</td>
</tr>
<tr>
<td><code>[1]</code></td>
<td><code>{ execute, loading, error }</code></td>
<td>Manual re-fetch control. Call <code>execute()</code> to trigger a new fetch.</td>
</tr>
<tr>
<td><code>[2]</code></td>
<td><code>(data: Data) =&gt; void</code></td>
<td>Setter for optimistic updates — replaces the stored value without a network call.</td>
</tr>
<tr>
<td><code>[3].waitForResult</code></td>
<td><code>() =&gt; Promise&lt;Data&gt;</code></td>
<td>Resolves when a non-null value becomes available.</td>
</tr>
<tr>
<td><code>[3].data$</code></td>
<td><code>MutableRefObject&lt;Data | null&gt;</code></td>
<td>A ref to the current value for use in callbacks without closure staleness.</td>
</tr>
</tbody>
</table>
<a id="usage-4" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Usage<a href="#usage-4" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useAsyncValue</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">UserProfile</span><span class="hl-1">({ </span><span class="hl-2">userId</span><span class="hl-1"> }: { </span><span class="hl-2">userId</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1"> }) {</span><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> [</span><span class="hl-10">user</span><span class="hl-1">, { </span><span class="hl-10">loading</span><span class="hl-1">, </span><span class="hl-10">error</span><span class="hl-1"> }, </span><span class="hl-10">setUser</span><span class="hl-1">] = </span><span class="hl-5">useAsyncValue</span><span class="hl-1">(</span><br/><span class="hl-1">    </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">getUser</span><span class="hl-1">(</span><span class="hl-2">userId</span><span class="hl-1">),</span><br/><span class="hl-1">    { </span><span class="hl-2">deps:</span><span class="hl-1"> [</span><span class="hl-2">userId</span><span class="hl-1">] }</span><br/><span class="hl-1">  );</span><br/><br/><span class="hl-1">  </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">loading</span><span class="hl-1">) </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-6">&lt;</span><span class="hl-7">Spinner</span><span class="hl-1"> </span><span class="hl-6">/&gt;</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">error</span><span class="hl-1"> || !</span><span class="hl-2">user</span><span class="hl-1">) </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-6">&lt;</span><span class="hl-7">ErrorMessage</span><span class="hl-1"> </span><span class="hl-6">/&gt;</span><span class="hl-1">;</span><br/><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">handleRename</span><span class="hl-1"> = </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-2">name</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">updated</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">api</span><span class="hl-1">.</span><span class="hl-5">updateUser</span><span class="hl-1">(</span><span class="hl-2">userId</span><span class="hl-1">, { </span><span class="hl-2">name</span><span class="hl-1"> });</span><br/><span class="hl-1">    </span><span class="hl-5">setUser</span><span class="hl-1">(</span><span class="hl-2">updated</span><span class="hl-1">); </span><span class="hl-17">// optimistic update — no refetch</span><br/><span class="hl-1">  };</span><br/><br/><span class="hl-1">  </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-6">&lt;</span><span class="hl-7">UserCard</span><span class="hl-1"> </span><span class="hl-8">user</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">user</span><span class="hl-4">}</span><span class="hl-1"> </span><span class="hl-8">onRename</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">handleRename</span><span class="hl-4">}</span><span class="hl-1"> </span><span class="hl-6">/&gt;</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<hr>
<a id="usepreventaction" class="tsd-anchor"></a><h2 class="tsd-anchor-link">usePreventAction<a href="#usepreventaction" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>A <strong>counting semaphore</strong> that tracks how many async operations are currently in flight. Pass <code>handleLoadStart</code> and <code>handleLoadEnd</code> as <code>onLoadStart</code>/<code>onLoadEnd</code> props to multiple buttons, and they all share a single <code>loading</code> flag. While any one is running, the <code>loading</code> boolean is <code>true</code>, so you can disable them all simultaneously.</p>
<a id="signature-5" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Signature<a href="#signature-5" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="ts"><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">usePreventAction</span><span class="hl-1">(</span><span class="hl-2">options</span><span class="hl-1">?: {</span><br/><span class="hl-1">  </span><span class="hl-2">disabled</span><span class="hl-1">?: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-5">onLoadStart</span><span class="hl-1">?: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-5">onLoadEnd</span><span class="hl-1">?: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">}): {</span><br/><span class="hl-1">  </span><span class="hl-5">handleLoadStart</span><span class="hl-1">: () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-5">handleLoadEnd</span><span class="hl-1">: (</span><span class="hl-2">isOk</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-7">void</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-2">loading</span><span class="hl-1">: </span><span class="hl-7">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

<a id="parameters-5" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Parameters<a href="#parameters-5" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><strong><code>options.disabled</code></strong><code>boolean</code></p>
<p>When <code>true</code>, forces <code>loading</code> to <code>true</code> regardless of in-flight operations. Useful for propagating an external disabled state.</p>
<p><strong><code>options.onLoadStart</code></strong><code>() =&gt; void</code></p>
<p>Forwarded callback called each time any tracked operation starts.</p>
<p><strong><code>options.onLoadEnd</code></strong><code>(isOk: boolean) =&gt; void</code></p>
<p>Forwarded callback called each time any tracked operation ends.</p>
<a id="return-value-5" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Return value<a href="#return-value-5" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>handleLoadStart</code></td>
<td><code>() =&gt; void</code></td>
<td>Increments the internal counter. Pass as <code>onLoadStart</code> to each <code>ActionButton</code>.</td>
</tr>
<tr>
<td><code>handleLoadEnd</code></td>
<td><code>(isOk: boolean) =&gt; void</code></td>
<td>Decrements the counter. Pass as <code>onLoadEnd</code> to each <code>ActionButton</code>.</td>
</tr>
<tr>
<td><code>loading</code></td>
<td><code>boolean</code></td>
<td><code>true</code> when the counter is greater than zero, or when <code>disabled</code> is <code>true</code>.</td>
</tr>
</tbody>
</table>
<a id="usage-5" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Usage<a href="#usage-5" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">usePreventAction</span><span class="hl-1">, </span><span class="hl-2">ActionButton</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">function</span><span class="hl-1"> </span><span class="hl-5">ToolBar</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-10">handleLoadStart</span><span class="hl-1">, </span><span class="hl-10">handleLoadEnd</span><span class="hl-1">, </span><span class="hl-10">loading</span><span class="hl-1"> } = </span><span class="hl-5">usePreventAction</span><span class="hl-1">();</span><br/><br/><span class="hl-1">  </span><span class="hl-0">return</span><span class="hl-1"> (</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;&gt;</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;</span><span class="hl-7">ActionButton</span><br/><span class="hl-1">        </span><span class="hl-8">disabled</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-4">}</span><br/><span class="hl-1">        </span><span class="hl-8">onLoadStart</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">handleLoadStart</span><span class="hl-4">}</span><br/><span class="hl-1">        </span><span class="hl-8">onLoadEnd</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">handleLoadEnd</span><span class="hl-4">}</span><br/><span class="hl-1">        </span><span class="hl-8">onClick</span><span class="hl-1">=</span><span class="hl-4">{async</span><span class="hl-9"> () </span><span class="hl-4">=&gt;</span><span class="hl-9"> </span><span class="hl-2">api</span><span class="hl-9">.</span><span class="hl-5">doAction1</span><span class="hl-9">()</span><span class="hl-4">}</span><br/><span class="hl-1">      </span><span class="hl-6">&gt;</span><br/><span class="hl-1">        Action 1</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;/</span><span class="hl-7">ActionButton</span><span class="hl-6">&gt;</span><br/><br/><span class="hl-1">      </span><span class="hl-6">&lt;</span><span class="hl-7">ActionButton</span><br/><span class="hl-1">        </span><span class="hl-8">disabled</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">loading</span><span class="hl-4">}</span><br/><span class="hl-1">        </span><span class="hl-8">onLoadStart</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">handleLoadStart</span><span class="hl-4">}</span><br/><span class="hl-1">        </span><span class="hl-8">onLoadEnd</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">handleLoadEnd</span><span class="hl-4">}</span><br/><span class="hl-1">        </span><span class="hl-8">onClick</span><span class="hl-1">=</span><span class="hl-4">{async</span><span class="hl-9"> () </span><span class="hl-4">=&gt;</span><span class="hl-9"> </span><span class="hl-2">api</span><span class="hl-9">.</span><span class="hl-5">doAction2</span><span class="hl-9">()</span><span class="hl-4">}</span><br/><span class="hl-1">      </span><span class="hl-6">&gt;</span><br/><span class="hl-1">        Action 2</span><br/><span class="hl-1">      </span><span class="hl-6">&lt;/</span><span class="hl-7">ActionButton</span><span class="hl-6">&gt;</span><br/><span class="hl-1">    </span><span class="hl-6">&lt;/&gt;</span><br/><span class="hl-1">  );</span><br/><span class="hl-1">}</span>
</code><button type="button">Copy</button></pre>

</div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#async-hooks-usesinglerunaction-usequeuedaction-and-more"><span>Async hooks: use<wbr/>Singlerun<wbr/>Action, use<wbr/>Queued<wbr/>Action, and more</span></a><ul><li><a href="#usesinglerunaction"><span>use<wbr/>Singlerun<wbr/>Action</span></a></li><li><ul><li><a href="#signature"><span>Signature</span></a></li><li><a href="#parameters"><span>Parameters</span></a></li><li><a href="#return-value"><span>Return value</span></a></li><li><a href="#usage"><span>Usage</span></a></li></ul></li><li><a href="#usequeuedaction"><span>use<wbr/>Queued<wbr/>Action</span></a></li><li><ul><li><a href="#signature-1"><span>Signature</span></a></li><li><a href="#parameters-1"><span>Parameters</span></a></li><li><a href="#return-value-1"><span>Return value</span></a></li><li><a href="#usage-1"><span>Usage</span></a></li></ul></li><li><a href="#useasyncaction"><span>use<wbr/>Async<wbr/>Action</span></a></li><li><ul><li><a href="#signature-2"><span>Signature</span></a></li><li><a href="#parameters-2"><span>Parameters</span></a></li><li><a href="#return-value-2"><span>Return value</span></a></li><li><a href="#usage-2"><span>Usage</span></a></li></ul></li><li><a href="#useasyncprogress"><span>use<wbr/>Async<wbr/>Progress</span></a></li><li><ul><li><a href="#signature-3"><span>Signature</span></a></li><li><a href="#parameters-3"><span>Parameters</span></a></li><li><a href="#return-value-3"><span>Return value</span></a></li><li><a href="#usage-3"><span>Usage</span></a></li></ul></li><li><a href="#useasyncvalue"><span>use<wbr/>Async<wbr/>Value</span></a></li><li><ul><li><a href="#signature-4"><span>Signature</span></a></li><li><a href="#parameters-4"><span>Parameters</span></a></li><li><a href="#return-value-4"><span>Return value</span></a></li><li><a href="#usage-4"><span>Usage</span></a></li></ul></li><li><a href="#usepreventaction"><span>use<wbr/>Prevent<wbr/>Action</span></a></li><li><ul><li><a href="#signature-5"><span>Signature</span></a></li><li><a href="#parameters-5"><span>Parameters</span></a></li><li><a href="#return-value-5"><span>Return value</span></a></li><li><a href="#usage-5"><span>Usage</span></a></li></ul></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">react-declarative</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>