Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Cesium React Integration

Norman Fomferra edited this page Nov 21, 2016 · 10 revisions

Requirement

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.

Challenge

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.

Strategies

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 by Tab change, we could move its real DOM element into the body element and hide it. When the Tab is selected again, we move it out of the body and show it back in its TabPanel 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

Google Results

  • 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

Related Issues