Skip to content

Commit 8207452

Browse files
committed
perf(hooks): use setTimeout instead of flushSync to update state
1 parent a71e64b commit 8207452

File tree

2 files changed

+29
-31
lines changed

2 files changed

+29
-31
lines changed

packages/next-safe-action/src/hooks.ts

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import { isNotFoundError } from "next/dist/client/components/not-found.js";
44
import { isRedirectError } from "next/dist/client/components/redirect.js";
55
import * as React from "react";
6-
import * as ReactDOM from "react-dom";
76
import {} from "react/experimental";
87
import type {} from "zod";
98
import type { InferIn, Schema } from "./adapters/types";
@@ -41,6 +40,12 @@ export const useAction = <
4140

4241
const execute = React.useCallback(
4342
(input: S extends Schema ? InferIn<S> : void) => {
43+
setTimeout(() => {
44+
setIsIdle(false);
45+
setClientInput(input);
46+
setIsExecuting(true);
47+
}, 0);
48+
4449
startTransition(() => {
4550
safeActionFn(input as S extends Schema ? InferIn<S> : undefined)
4651
.then((res) => setResult(res ?? {}))
@@ -55,19 +60,19 @@ export const useAction = <
5560
setIsExecuting(false);
5661
});
5762
});
58-
59-
ReactDOM.flushSync(() => {
60-
setIsIdle(false);
61-
setClientInput(input);
62-
setIsExecuting(true);
63-
});
6463
},
6564
[safeActionFn]
6665
);
6766

6867
const executeAsync = React.useCallback(
6968
(input: S extends Schema ? InferIn<S> : void) => {
7069
const fn = new Promise<Awaited<ReturnType<typeof safeActionFn>>>((resolve, reject) => {
70+
setTimeout(() => {
71+
setIsIdle(false);
72+
setClientInput(input);
73+
setIsExecuting(true);
74+
}, 0);
75+
7176
startTransition(() => {
7277
safeActionFn(input as S extends Schema ? InferIn<S> : undefined)
7378
.then((res) => {
@@ -88,12 +93,6 @@ export const useAction = <
8893
});
8994
});
9095

91-
ReactDOM.flushSync(() => {
92-
setIsIdle(false);
93-
setClientInput(input);
94-
setIsExecuting(true);
95-
});
96-
9796
return fn;
9897
},
9998
[safeActionFn]
@@ -165,6 +164,12 @@ export const useOptimisticAction = <
165164

166165
const execute = React.useCallback(
167166
(input: S extends Schema ? InferIn<S> : void) => {
167+
setTimeout(() => {
168+
setIsIdle(false);
169+
setClientInput(input);
170+
setIsExecuting(true);
171+
}, 0);
172+
168173
startTransition(() => {
169174
setOptimisticValue(input as S extends Schema ? InferIn<S> : undefined);
170175
safeActionFn(input as S extends Schema ? InferIn<S> : undefined)
@@ -180,19 +185,19 @@ export const useOptimisticAction = <
180185
setIsExecuting(false);
181186
});
182187
});
183-
184-
ReactDOM.flushSync(() => {
185-
setIsIdle(false);
186-
setClientInput(input);
187-
setIsExecuting(true);
188-
});
189188
},
190189
[safeActionFn, setOptimisticValue]
191190
);
192191

193192
const executeAsync = React.useCallback(
194193
(input: S extends Schema ? InferIn<S> : void) => {
195194
const fn = new Promise<Awaited<ReturnType<typeof safeActionFn>>>((resolve, reject) => {
195+
setTimeout(() => {
196+
setIsIdle(false);
197+
setClientInput(input);
198+
setIsExecuting(true);
199+
}, 0);
200+
196201
startTransition(() => {
197202
setOptimisticValue(input as S extends Schema ? InferIn<S> : undefined);
198203
safeActionFn(input as S extends Schema ? InferIn<S> : undefined)
@@ -214,12 +219,6 @@ export const useOptimisticAction = <
214219
});
215220
});
216221

217-
ReactDOM.flushSync(() => {
218-
setIsIdle(false);
219-
setClientInput(input);
220-
setIsExecuting(true);
221-
});
222-
223222
return fn;
224223
},
225224
[safeActionFn, setOptimisticValue]

packages/next-safe-action/src/stateful-hooks.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22

33
import * as React from "react";
4-
import * as ReactDOM from "react-dom";
54
import {} from "react/experimental";
65
import type {} from "zod";
76
import type { InferIn, Schema } from "./adapters/types";
@@ -45,13 +44,13 @@ export const useStateAction = <
4544

4645
const execute = React.useCallback(
4746
(input: S extends Schema ? InferIn<S> : void) => {
48-
startTransition(() => {
49-
dispatcher(input as S extends Schema ? InferIn<S> : undefined);
50-
});
51-
52-
ReactDOM.flushSync(() => {
47+
setTimeout(() => {
5348
setIsIdle(false);
5449
setClientInput(input);
50+
}, 0);
51+
52+
startTransition(() => {
53+
dispatcher(input as S extends Schema ? InferIn<S> : undefined);
5554
});
5655
},
5756
[dispatcher]

0 commit comments

Comments
 (0)