fix(home): onboarding slot uses a module-level lazy (no component chosen during render); warm-snapshot tests load the city table like the boot does
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
31d0737897
commit
e2c3791fad
@@ -1,22 +1,38 @@
|
||||
"use client";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
import { lazy, Suspense } from "react";
|
||||
|
||||
import type { HomeOnboardingShellProps } from "@/components/home-onboarding-shell";
|
||||
import type { HomeOnboardingShell, HomeOnboardingShellProps } from "@/components/home-onboarding-shell";
|
||||
import { loadedHomeOnboardingShell, loadHomeOnboardingShell } from "@/lib/home-onboarding-shell-loader";
|
||||
|
||||
// Only reached when the preload below did not finish (or failed) before the
|
||||
// shell had to paint; renders nothing until the chunk arrives, never a spinner.
|
||||
const DynamicHomeOnboardingShell = dynamic(loadHomeOnboardingShell, { loading: () => null });
|
||||
type ShellModule = { default: typeof HomeOnboardingShell };
|
||||
|
||||
/**
|
||||
* The onboarding shell (birth-place picker, China city table, birth-time
|
||||
* intake) is only for people whose profile is incomplete, so it left the home
|
||||
* first-screen bundle (TASK-home-first-load T7, BUG-1130). The cold boot
|
||||
* preloads it before reveal when the profile is incomplete, so this renders the
|
||||
* loaded component directly and the reveal shows it in the same frame.
|
||||
* preloads it before reveal when the profile is incomplete; `lazy` is then
|
||||
* handed an already-settled thenable, which React resolves synchronously, so
|
||||
* the reveal shows the shell in the same frame. Without the preload it loads
|
||||
* behind an empty fallback — never a spinner.
|
||||
*/
|
||||
const LazyHomeOnboardingShell = lazy((): Promise<ShellModule> => {
|
||||
const loaded = loadedHomeOnboardingShell();
|
||||
if (loaded) {
|
||||
// A thenable that calls back synchronously: React marks the lazy resolved
|
||||
// before it would suspend.
|
||||
const settled: PromiseLike<ShellModule> = {
|
||||
then: (resolve) => Promise.resolve(resolve ? resolve({ default: loaded }) : { default: loaded }) as never,
|
||||
};
|
||||
return settled as Promise<ShellModule>;
|
||||
}
|
||||
return loadHomeOnboardingShell().then((Shell) => ({ default: Shell }));
|
||||
});
|
||||
|
||||
export function HomeOnboardingShellSlot(props: HomeOnboardingShellProps) {
|
||||
const Loaded = loadedHomeOnboardingShell();
|
||||
return Loaded ? <Loaded {...props} /> : <DynamicHomeOnboardingShell {...props} />;
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LazyHomeOnboardingShell {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user