Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImageryLayer does not re-render when WMS imagery provider changes #634

Open
wxmann opened this issue Oct 2, 2023 · 1 comment
Open

ImageryLayer does not re-render when WMS imagery provider changes #634

wxmann opened this issue Oct 2, 2023 · 1 comment

Comments

@wxmann
Copy link

wxmann commented Oct 2, 2023

I am trying to show some meteorological data on a Cesium viewer, where the user can toggle the vertical level and the kind of data being shown coming from a WMS data source. I have a component which takes the level and the layers (kind of data) attribute, and whenever the user toggles either I want the viewer to update the meteorological data accordingly. However, this is not happening. Here is the basic gist of the code:

const BASE_IMAGERY_ATTRS = {
  url: 'blah',
  // some other attributes
}
export default function Layer({ level, layers }) {
  const [imageryProvider, setImageryProvider] = useState();
  useEffect(() => {
    setImageryProvider(new WebMapServiceImageryProvider({
      ...BASE_IMAGERY_ATTRS,
      layers,
      parameters: { level },
    }));
  }, [level, layers];

  return (
    <ImageryLayer 
       imageryProvider={imageryProvider} 
       // other props for alpha, show, etc.
     /> 
  )
}

And of course this component is a child under a Viewer.

When I inspect/log the Cesium elements under the hood and the observe the outgoing HTTP requests to the WMS, I can see the layers and parameters don't change from the default values. However, according to the guide, if a readonly property (such as the imageryProvider) changes or gets reinstantiated, the Cesium component should be "destroyed and reinitialized." But it's not doing so here.

If I work around this and do this imperatively using Cesium classes by capturing a ref of the ImageryLayerCollection, the components get swapped out and the meteorological data updates correctly. So I think the lack of rerendering is happening on Resium's side. Here's the imperative code that works:

export default function Layer2({ level, layers }) {
  const collectionRef = useRef();
  useEffect(() => {
    const collection = collectionRef?.current?.cesiumElement;
    if (collection) {
      const index = //some hard-coded index;
      const prevLayer = collection.get(index);
      collection.remove(prevLayer);
  
      const newLayer = new WebMapServiceImageryProvider({
        ...BASE_IMAGERY_ATTRS,
        layers,
        parameters: { level },
      }));
      collection.add(new ImageryLayer(newLayer, {// alpha/show/etc options}), index);
    }
  }, [level, layers, collectionRef];

  return (
    <ImageryLayerCollection ref={collectionRef} />
  )
}

Versions:
Cesium: 1.108.0
Resium: 1.17.1
Next.js: 13.4.19 (but not using the /app directory or server-side components)

@BenDDev
Copy link

BenDDev commented Feb 28, 2024

I've just stumbled into this issue after updating to 1.17.x (from 1.15.x). We're using the WMS sld_body parameter with GeoServer to dynamically style layers (by selecting configurable styles). This completely breaks this functionality as any new SLD Body (which causes a new imagery provider to be created) doesn't trigger a re-render.

I've found a workaround by passing a key which is based on the sld_body (which is the dynamic part). It works but the SLD string has the potential to be very long, so feels a bit hacky.

You used to have to try to stop it from re-rendering, whereas now you have to trick into re-rendering!

Versions:
Cesium: 1.114.0
Resium: 1.17.2
Remix (w/ Vite) - I checked using just Vite (no frameworks) and found the same issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants