-
Notifications
You must be signed in to change notification settings - Fork 5
Cesium React Integration
To use Cesium with React in cate-desktop we need to wrap a Cesium.Viewer or
Cesium.CesiumWidget into a React.Component. We need a CesiumComponent
.
Cesium.CesiumWidget holds a lot of state (layers, placemarks, perspective, terrain, imagery providers) which it renders into HTML canvas element. This doesn't seem to fit well with the React way of rendering the DOM, as both virtual DOM and real DOM elements are being destroyed once a React component is no longer part of the UI. This behavior is what we currently have when using Cesium in a blueprint Tabs component. If a new Tab
is selected, the old TabPanel
is no longer part of the UI. This will destroy the CesiumComponent
and its containing Cesium canvas. When the Cesium Tab
is clicked again, a new Cesium Viewer/Widget is created from scratch - with major performance impact.
Maybe this is a common problem in React, however I (Norman) have not yet found any valuable information of how to achieve the requirement. Here are some possible strategies to be investigated further:
- Use a global cache to retrieve an "alive" Cesium.Viewer (or Cesium.CesiumWidget) instance and its associated virtual DOM parent. Remove from cache only if no longer in use (e.g. user closes the window containing the Cesium globe), then explicitly destroy instances. Let
CesiumComponent.render()
return virtual DOM parents from global cache. This seems to be a bad solution w.r.t. design and the React way of doing things. tested and it works! Implemented as abstract base class PermanentComponent which is implemented by CesiumComponent and OpenLayersComponent. - Use React's dangerouslySetInnerHTML attribute to inject a real Cesium viewer/widget canvas into a React virtual DOM element taken from a cache. tested: doesn't work because
dangerouslySetInnerHTML
must be a string - When the
CesiumComponent
gets unmounted byTab
change, we could move its real DOM element into the body element and hide it. When theTab
is selected again, we move it out of the body and show it back in itsTabPanel
Panel component. Technical solution is provide here. tested: doesn't help, because React components cannot control which real DOM elements from virtual DOM element - Exploit React's Reconciliation algorithm to somehow let the Cesium widget/viewer instance survive DOM updates. not tested yet, but seems not to help at all
- Is anyone using cesium with Reactjs?: "Our approach is to keep Cesium "outside" the React DOM so we don't have to fight it. If React were to repeatedly create/destroy the Cesium window according to its component life cycle, that would be bad, but of course there are other ways to avoid that if you don't like our approach."
- Aviture/react-cesium: A short example on how to keep the Cesium map in sync "the React way".
- markerikson/react-redux-cesium-testing-demo: A sample project demonstrating configuration of React, Redux, Webpack, Cesium, and Mocha
- https://github.com/angular/angular/issues/5275 describes a similar problem in Angular JS