I have tried using
var viewer = document.getElementById("cesiumContainer")
but this doesn't return the actual viewer object. What's the correct approach to get an instance of/reference to the viewer that's been created already. I'm trying to get access to it in a part of my code that is out of scope with the part where I created the viewer, if that wasn't obvious.
The viewer is being created using the resium
package for a react app with <Viewer>
. The HTML page that renders still wraps the viewer in a div with the id cesiumContainer
and from inspecting the source in dev tools it looks the same as it would without react, so I would think it would behave the same in terms of being able to access it. Of course that may not be the case.
This answer focuses on your use of Resium, Cesium and class based React Components.
If you are using React 16+ you can use Context to achieve your goal.
export const state = {viewer: '', setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
contextType
to the React Contact reference. (CesiumContext
). In the ViewerComponent constructor use createRef()
. It will capture the only prop (ref
) that will allow the Context state to be set, thereby allowing all other components access to the reference. Note the use of componentDidMount()
to set the state of the context to there reference provided by Resium.export default class ViewerComponent extends React.Component {
constructor(props) {
super(props);
this.ref = createRef();
}
componentDidMount() {
if (this.ref.current && this.ref.current.cesiumElement) {
this.context.setInstance(this.ref.current.cesiumElement);
}
}
render() {
return <Viewer ref={this.ref}/>
}
}
ViewerComponent.contextType = CesiumContext;
ViewComponent
renders/mounts, and the Context state is set, then every Child component under the Context element has access to the current Cesium View object. There is a problem created by this structure in that in order for this to happen, the tree must be rerendered. Based upon your app you may have to force the rerendering. <div className="App">
<CesiumContext.Provider value={state}>
<ViewerComponent/>
<AComponent/>
<BComponent/>
</CesiumContext.Provider>
</div>
contextType
on the class. In the componentDidMount
grab the instance from the context.export default class AComponent extends React.Component {
constructor() {
super();
this.viewer = false;
}
componentDidMount() {
this.viewer = this.context.viewer;
}
render() {
return <p>{/* do something with this.viewer */}</p>;
}
}
AComponent.contextType = CesiumContext;
A complete solution demonstrates this below. One component AComponent
accesses the Cesium.View.shadowed property and 'BComponent` accesses the Cesium.View. allowDataSourcesToSuspendAnimation property.