Hello. A React newbie here.
I have a long script and for the purpose of managing the code I split it to different components.
I have the widget (parent) component that I store the selected map in the jimuMapView.
Then, I have the children components that need to use the props of the jimuMapView so they add layers and graphics to that map, or other actions like zoom and so forth.
So, my question is how in the children components I can access the jimuMapView from the parent to add the layers?
None of the documentation or examples in ESRI address this scenario.
@RobertScheitlin__GISP , @Grant-S-Carroll or anyone else? Thank you.
activeViewChangeHandler = (jmv: JimuMapView) => {
if (jmv) {this.setState({ jimuMapView: jmv }); }
};
<div className="widget-addLayers jimu-widget p-2">
{this.props.hasOwnProperty("useMapWidgetIds") &&
this.props.useMapWidgetIds &&
this.props.useMapWidgetIds[0] && (
<JimuMapViewComponent
useMapWidgetId={this.props.useMapWidgetIds?.[0]}
onActiveViewChange={this.activeViewChangeHandler}
/>
)}
Solved! Go to Solution.
Hi There
There are a couple of ways of achieving this, depending of what your are trying to do in your child component.
1. You can simply pass the jimuMapView through in to your child component, by making the mapView a prop of the child component, see below.
In your child component, create an interface for the props.
Then reference these in the class/function depending on what pattern you are using.
You can then access the map via this.props.mapView
2. The second appropach is ito pass in functions from the parent component that act on the mapView.
As before within your props interface in your child component, add in a reference to the function.
Then when you need to call this function within the child, call this.props.<functionName>
Within the parent component, it looks like this.
In the example above, the parent component is actual a child component of widget.tsx, so I have passed the mapView down several times.
Hopefully that all makes sense?
Cheers
You just need to make sure that you have declared the mapView as the right type. Its not a jimuMapView you are assigning the view property of the jimuMapView, which can either be a MapView or a SceneView.
Component did mount will only fire once, when the component is mounted in to the DOM. At that stage, the map will most likely not have loaded, hence why using activeViewChange is the best place to capture when the map has loaded.
Hi There
There are a couple of ways of achieving this, depending of what your are trying to do in your child component.
1. You can simply pass the jimuMapView through in to your child component, by making the mapView a prop of the child component, see below.
In your child component, create an interface for the props.
Then reference these in the class/function depending on what pattern you are using.
You can then access the map via this.props.mapView
2. The second appropach is ito pass in functions from the parent component that act on the mapView.
As before within your props interface in your child component, add in a reference to the function.
Then when you need to call this function within the child, call this.props.<functionName>
Within the parent component, it looks like this.
In the example above, the parent component is actual a child component of widget.tsx, so I have passed the mapView down several times.
Hopefully that all makes sense?
Cheers
THank you. I followed the first method I am almost there.
In the child component, I console log the
and I get this:
I want to access the this.props.mapView.view which it is a property because under it is the map module.
However, when I console log
I get the red underline that the view is not a property of the mapView, however the console outputs the x coordinate. Why does it works? I was able to add a layer using the this.props.mapView.view.map.add
This is confusing. Thank you.
@LefterisKoumis looks like you are passing the jimuMapView to your component and not the jimuMapView.view. I use method one that Grant suggested in most of my custom components and pass the actual view object and don't have any problems.
@RobertScheitlin__GISP After I was passing the jimuMapView.view to the the child component
<div>{<ChildComponent mapView={this.state.jimuMapView.view} />}</div>
I am getting the error "Cannot read properties of null (reading 'view')" at runtime. of the line above. It seems that there is async error. The 'this.state.jimuMapView' seems to be null.
To address it, I used this from the FeaturePanel, to no avail:
activeViewChangeHandler = (jimuMapView: JimuMapView) => {
if (null === jimuMapView || undefined === jimuMapView) {
this.setState({ jimuMapView: null });
return; //skip null
}
this.setState({ jimuMapView: jimuMapView });
};
How can the rendering of the component be delayed until the jimuMapView is not null.
Hi, apologies for lack of response, I'm in the throws of moving houses and islands. What you can do is store the actual mapView in state, not the jimuMapView, so in the onActiveViewChange do something like this.
onActiveViewChange = (jimuMapView: JimuMapView) => {
if (!(jimuMapView && jimuMapView.view)) {
return;
}
this.setState({ mapView:jimuMapView.view });
}
Then within your child component, you will need to handle the case where the view is null, but it should prevent the issues you are facing with the null value, as the re-render will occur anytime the state is updated.
Hope that helps.
Cheers
THank you.
I got this error.
Question. Should we use the componentDidMount to update the jimuMapView state to avoid async errors?
You just need to make sure that you have declared the mapView as the right type. Its not a jimuMapView you are assigning the view property of the jimuMapView, which can either be a MapView or a SceneView.
Component did mount will only fire once, when the component is mounted in to the DOM. At that stage, the map will most likely not have loaded, hence why using activeViewChange is the best place to capture when the map has loaded.
Yes, you are correct. What a novice mistake. Thank you.