diff --git a/.changeset/solid-pillows-laugh.md b/.changeset/solid-pillows-laugh.md new file mode 100644 index 000000000..4623d91cd --- /dev/null +++ b/.changeset/solid-pillows-laugh.md @@ -0,0 +1,5 @@ +--- +"@stackflow/react": minor +--- + +Improve scheduling of Activity preparation tasks by marking them as passive effects. diff --git a/integrations/react/src/future/useActivityPreparation.ts b/integrations/react/src/future/useActivityPreparation.ts index 53b4e4cc4..024b43c68 100644 --- a/integrations/react/src/future/useActivityPreparation.ts +++ b/integrations/react/src/future/useActivityPreparation.ts @@ -1,4 +1,5 @@ import type { RegisteredActivityName } from "@stackflow/config"; +import { useEffect } from "react"; import { usePrepare } from "./usePrepare"; export function useActivityPreparation( @@ -6,7 +7,9 @@ export function useActivityPreparation( ) { const prepare = usePrepare(); - for (const { activityName } of activities) { - prepare(activityName); - } + useEffect(() => { + for (const { activityName } of activities) { + prepare(activityName); + } + }, [activities, prepare]); } diff --git a/integrations/react/src/future/usePrepare.ts b/integrations/react/src/future/usePrepare.ts index fb895069f..f83d4a0a7 100644 --- a/integrations/react/src/future/usePrepare.ts +++ b/integrations/react/src/future/usePrepare.ts @@ -2,6 +2,7 @@ import type { InferActivityParams, RegisteredActivityName, } from "@stackflow/config"; +import { useCallback } from "react"; import { useActivityComponentMap } from "../__internal__/ActivityComponentMapProvider"; import { isStructuredActivityComponent } from "../__internal__/StructuredActivityComponentType"; import { useDataLoader } from "./loader"; @@ -17,37 +18,40 @@ export function usePrepare(): Prepare { const loadData = useDataLoader(); const activityComponentMap = useActivityComponentMap(); - return async function prepare( - activityName: K, - activityParams?: InferActivityParams, - ) { - const activityConfig = config.activities.find( - ({ name }) => name === activityName, - ); - const prefetchTasks: Promise[] = []; - - if (!activityConfig) - throw new Error(`Activity ${activityName} is not registered.`); - - if (activityParams && activityConfig.loader) { - prefetchTasks.push( - Promise.resolve(loadData(activityName, activityParams)), - ); - } - - if ("_load" in activityComponentMap[activityName]) { - prefetchTasks.push( - Promise.resolve(activityComponentMap[activityName]._load?.()), - ); - } - - if ( - isStructuredActivityComponent(activityComponentMap[activityName]) && - typeof activityComponentMap[activityName].content === "function" + return useCallback( + async function prepare( + activityName: K, + activityParams?: InferActivityParams, ) { - prefetchTasks.push(activityComponentMap[activityName].content()); - } - - await Promise.all(prefetchTasks); - }; + const activityConfig = config.activities.find( + ({ name }) => name === activityName, + ); + const prefetchTasks: Promise[] = []; + + if (!activityConfig) + throw new Error(`Activity ${activityName} is not registered.`); + + if (activityParams && activityConfig.loader) { + prefetchTasks.push( + Promise.resolve(loadData(activityName, activityParams)), + ); + } + + if ("_load" in activityComponentMap[activityName]) { + prefetchTasks.push( + Promise.resolve(activityComponentMap[activityName]._load?.()), + ); + } + + if ( + isStructuredActivityComponent(activityComponentMap[activityName]) && + typeof activityComponentMap[activityName].content === "function" + ) { + prefetchTasks.push(activityComponentMap[activityName].content()); + } + + await Promise.all(prefetchTasks); + }, + [config, loadData, activityComponentMap], + ); }