Cesium Ion NextJS country borders

Hi,

I need help adding borders trough either a .KML or .geojson file, i tried both and getting the same error

TypeError: Cannot read properties of undefined (reading ‘dataSources’)

124 |
125 | return () => {

126 | if (viewer.dataSources) {
| ^
127 | viewer.dataSources.remove(geoJsonDataSource);
128 | }
129 | };

The error happends in the useEffect hook


  useEffect(() => {
  const viewer = viewerRef.current;
  if (!viewer) return;

  const geoJsonDataSource = new Cesium.GeoJsonDataSource();
  viewer.dataSources.add(geoJsonDataSource);

  geoJsonDataSource.load('/geo/countries.kml');

  return () => {
    if (viewer.dataSources) {
      viewer.dataSources.remove(geoJsonDataSource);
    }
  };
}, []);

Even with the if statement and the fact that viewerRef.current is defined in another hook called before this one

useEffect(() => {
    if (!cesiumContainerRef.current || viewerRef.current) return;
    /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/
    (window as any).CESIUM_BASE_URL = "/Cesium/";
    Cesium.Ion.defaultAccessToken = CESIUM_ACCESS_TOKEN ?? "";
    

    try {
      viewerRef.current = new Cesium.Viewer(cesiumContainerRef.current, {
        timeline: false,
        animation: false,
        baseLayerPicker: false,
      });
    } catch (err) {
      console.error("Cesium failed to initialize:", err);
      message.error("Cesium Viewer failed to initialize.");
    }

    return () => {
      viewerRef.current?.destroy();
      viewerRef.current = null;
    };
  }, []);

Welcome to the Cesium community @d4v3xx

This sounds like an issue with Cesium JS more that the Cesium ion services, so I am going to move it to to the Cesium JS group for better visiblity.

Looking at the code I’m not sure where it is going wrong. The one thing I would suggest is checking viewer.isDestroyed in the effect cleanup. If the viewer has already been destroyed them you don’t need to do anything else.

Hi @d4v3xx, welcome to the community!

I think @mdc9001 already touched on the main issue. In the useEffect snippet you posted, the return value is an anonymous function that could be called at any time. It looks like this function is being called after viewerRef.current was destroyed.

One simple fix: re-check the existence of viewer before checking viewer.dataSources:

  return () => {
    if (viewer && viewer.dataSources) {
      viewer.dataSources.remove(geoJsonDataSource);
    }
  };