Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/solid-pillows-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackflow/react": minor
---

Improve scheduling of Activity preparation tasks by marking them as passive effects.
9 changes: 6 additions & 3 deletions integrations/react/src/future/useActivityPreparation.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import type { RegisteredActivityName } from "@stackflow/config";
import { useEffect } from "react";
import { usePrepare } from "./usePrepare";

export function useActivityPreparation(
activities: { activityName: RegisteredActivityName }[],
) {
const prepare = usePrepare();

for (const { activityName } of activities) {
prepare(activityName);
}
useEffect(() => {
for (const { activityName } of activities) {
prepare(activityName);
}
}, [activities, prepare]);
}
68 changes: 36 additions & 32 deletions integrations/react/src/future/usePrepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -17,37 +18,40 @@ export function usePrepare(): Prepare {
const loadData = useDataLoader();
const activityComponentMap = useActivityComponentMap();

return async function prepare<K extends RegisteredActivityName>(
activityName: K,
activityParams?: InferActivityParams<K>,
) {
const activityConfig = config.activities.find(
({ name }) => name === activityName,
);
const prefetchTasks: Promise<unknown>[] = [];

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<K extends RegisteredActivityName>(
activityName: K,
activityParams?: InferActivityParams<K>,
) {
prefetchTasks.push(activityComponentMap[activityName].content());
}

await Promise.all(prefetchTasks);
};
const activityConfig = config.activities.find(
({ name }) => name === activityName,
);
const prefetchTasks: Promise<unknown>[] = [];

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],
);
}
Loading