diff --git a/src/Globe/Globe.stories.tsx b/src/Globe/Globe.stories.tsx index 11dce26b..14c45046 100644 --- a/src/Globe/Globe.stories.tsx +++ b/src/Globe/Globe.stories.tsx @@ -1,8 +1,14 @@ import { action } from "@storybook/addon-actions"; import { Meta, StoryObj } from "@storybook/react"; -import { CesiumTerrainProvider, EllipsoidTerrainProvider, IonResource } from "cesium"; -import { StrictMode } from "react"; +import { + CesiumTerrainProvider, + EllipsoidTerrainProvider, + IonResource, + Viewer as CesiumViewer, +} from "cesium"; +import { StrictMode, useEffect, useRef } from "react"; +import { CesiumComponentRef } from "../core"; import Viewer from "../Viewer"; import Globe from "./Globe"; @@ -49,3 +55,95 @@ export const Promise: Story = { ), }; + +export const PromiseStrict: Story = { + args: { enableLighting: true, isTerrainEnabled: false } as any, + render: ({ isTerrainEnabled, ...args }: any) => ( + + + + + + ), +}; + +const DynamicComp = ({ isTerrainEnabled, ...args }: any) => { + const viewerRef = useRef | null>(null); + useEffect(() => { + const run = async () => { + if (!viewerRef.current?.cesiumElement) { + return; + } + + viewerRef.current.cesiumElement.terrainProvider = isTerrainEnabled + ? await CesiumTerrainProvider.fromUrl(IonResource.fromAssetId(1), { + requestVertexNormals: true, + requestWaterMask: false, + }) + : new EllipsoidTerrainProvider(); + }; + run(); + }, [viewerRef, isTerrainEnabled]); + + return ( + + + + ); +}; +export const Dynamic: Story = { + args: { enableLighting: true, isTerrainEnabled: false } as any, + render: ({ ...args }: any) => , +}; + +const DynamicStrictComp = ({ isTerrainEnabled, ...args }: any) => { + const viewerRef = useRef | null>(null); + useEffect(() => { + const run = () => { + // TODO: Remove this setTimeout in strict mode. + setTimeout(async () => { + if (!viewerRef.current?.cesiumElement) { + return; + } + + viewerRef.current.cesiumElement.terrainProvider = isTerrainEnabled + ? await CesiumTerrainProvider.fromUrl(IonResource.fromAssetId(1), { + requestVertexNormals: true, + requestWaterMask: false, + }) + : new EllipsoidTerrainProvider(); + }, 1); + }; + run(); + }, [viewerRef, isTerrainEnabled]); + + return ( + + + + ); +}; +export const DynamicStrict: Story = { + args: { enableLighting: true, isTerrainEnabled: false } as any, + render: ({ ...args }: any) => , +}; diff --git a/src/core/hooks.ts b/src/core/hooks.ts index 8e408673..99456704 100644 --- a/src/core/hooks.ts +++ b/src/core/hooks.ts @@ -135,7 +135,7 @@ export const useCesiumComponent = { + setMounted(false); + mountedRef.current = false; + }, []); + const unmount = useCallback(async () => { // Wait one tick to resolve Cesium's unmount process. await new Promise(r => queueMicrotask(() => r(undefined))); @@ -228,6 +236,7 @@ export const useCesiumComponent = { if (unmountReadyRef.current) { await unmountReadyRef.current; + unmountReadyRef.current = undefined; } mountReadyRef.current = mount(); }; @@ -270,10 +279,10 @@ export const useCesiumComponent = { // Need to update this state before Cesium is updated, // because Viewer's children must be hidden before it's unmounted. - setMounted(false); + beforeUnmount(); unmountReadyRef.current = unmount(); }; - }, [mount, unmount]); + }, [mount, unmount, beforeUnmount]); // Update properties of cesium element useEffect(() => { @@ -299,9 +308,13 @@ export const useCesiumComponent = ({ - cesiumElement: element.current, - })); + useImperativeHandle( + ref, + () => ({ + cesiumElement: mounted ? element.current : null, + }), + [mounted], + ); return [provided.current, mounted, wrapperRef]; };