diff --git a/.changeset/stable-useflow-actions.md b/.changeset/stable-useflow-actions.md new file mode 100644 index 000000000..140f6810c --- /dev/null +++ b/.changeset/stable-useflow-actions.md @@ -0,0 +1,7 @@ +--- +"@stackflow/react": patch +--- + +Memoize the action functions returned by `useFlow` and `useStepFlow` so their references stay stable across renders. + +Previously these hooks rebuilt their action object (`push`/`replace`/`pop`, `pushStep`/`replaceStep`/`popStep`) on every render, giving the returned functions a new reference each time. Since the underlying core actions are already a stable reference, the returned actions are now memoized on them (the same approach `usePrepare` already uses). This keeps the functions referentially stable when placed in `useEffect`/`useCallback` dependency arrays, avoiding unnecessary re-runs. diff --git a/integrations/react/src/useFlow.ts b/integrations/react/src/useFlow.ts index c121c1f98..7a547681d 100644 --- a/integrations/react/src/useFlow.ts +++ b/integrations/react/src/useFlow.ts @@ -1,5 +1,6 @@ -import { useCoreActions } from "./core"; +import { useMemo } from "react"; import type { Actions } from "./Actions"; +import { useCoreActions } from "./core"; import { makeActions } from "./makeActions"; export type FlowOutput = { @@ -9,5 +10,5 @@ export type FlowOutput = { export function useFlow(): Actions { const coreActions = useCoreActions(); - return makeActions(() => coreActions); + return useMemo(() => makeActions(() => coreActions), [coreActions]); } diff --git a/integrations/react/src/useStepFlow.ts b/integrations/react/src/useStepFlow.ts index 052a5cfec..3d21151e6 100644 --- a/integrations/react/src/useStepFlow.ts +++ b/integrations/react/src/useStepFlow.ts @@ -2,6 +2,7 @@ import type { InferActivityParams, RegisteredActivityName, } from "@stackflow/config"; +import { useMemo } from "react"; import { useCoreActions } from "./core"; import { makeStepActions } from "./makeStepActions"; import type { StepActions } from "./StepActions"; @@ -11,5 +12,5 @@ export function useStepFlow( ): StepActions> { const coreActions = useCoreActions(); - return makeStepActions(() => coreActions); + return useMemo(() => makeStepActions(() => coreActions), [coreActions]); }