How can I use Esri Arcgis Map in ReactJs Project?
Asked Answered
B

3

9

I'm trying to use Esri map. To include map in my project, here is what I found:

require([
    "esri/map",
    "esri/dijit/Search",
    "esri/dijit/LocateButton",
    "esri/geometry/Point",
    "esri/symbols/SimpleFillSymbol",
    "esri/symbols/SimpleMarkerSymbol",
    "esri/symbols/SimpleLineSymbol",

But there isn't any esri folder or npm package. Therefore, I'm confused here. How esri is imported in project?

Biodegradable answered 11/10, 2016 at 22:49 Comment(0)
F
5

Use esri-loader to load the required esri modules. This is a component rendering basemap.

import React, { Component } from 'react';
import { loadModules } from 'esri-loader';

const options = {
  url: 'https://js.arcgis.com/4.6/'
};

const styles =  {
  container: {
    height: '100vh',
    width: '100vw'
  },
  mapDiv: {
    padding: 0,
    margin: 0,
    height: '100%',
    width: '100%'
  },
}

class BaseMap extends Component {

  constructor(props) {
    super(props);
    this.state = {
      status: 'loading'
    }
  }

  componentDidMount() {
    loadModules(['esri/Map', 'esri/views/MapView'], options)
      .then(([Map, MapView]) => {
        const map = new Map({ basemap: "streets" });
        const view = new MapView({
          container: "viewDiv",
          map,
          zoom: 15,
          center: [78.4867, 17.3850]
        });
        view.then(() => {
          this.setState({
            map,
            view,
            status: 'loaded'
          });
        });
      })

  }

  renderMap() {
    if(this.state.status === 'loading') {
      return <div>loading</div>;
    }
  }

  render() {

    return(
          <div style={styles.container}>
            <div id='viewDiv' style={ styles.mapDiv } >
              {this.renderMap()}
            </div>
          </div>
    )
  }
}

export default BaseMap;

This renders a base map but this is not responsive. If I remove the div around the view div or if I give the height and width of the outer div (surrounding viewDiv) as relative ({ height: '100%', width: '100%'}), the map does not render. No idea why. Any suggestions to make it responsive would be appreciated.

Fourflush answered 21/2, 2018 at 9:27 Comment(1)
Can you please help me out to display popup or info window corresponding to each marker location on the map? #69631372Maine
G
3

An alternative method to the above is the one demonstrated in esri-react-router-example. That application uses a library called esri-loader to lazy load the ArcGIS API only in components/routes where it is needed. Example:

First, install the esri-loader libary:

npm install esri-loader --save

Then import the esri-loader functions in any react module:

import * as esriLoader from 'esri-loader'

Then lazy load the ArcGIS API:

componentDidMount () {
  if (!esriLoader.isLoaded()) {
    // lazy load the arcgis api
    const options = {
      // use a specific version instead of latest 4.x
      url: '//js.arcgis.com/3.18compact/'
    }
    esriLoader.bootstrap((err) => {
      if (err) {
        console.error(err)
      }
      // now that the arcgis api has loaded, we can create the map
      this._createMap()
    }, options)
  } else {
    // arcgis api is already loaded, just create the map
    this._createMap()
  }
},

Then load and the ArcGIS API's (Dojo) modules that are needed to create a map:

_createMap () {
  // get item id from route params or use default
  const itemId = this.props.params.itemId || '8e42e164d4174da09f61fe0d3f206641'
  // require the map class
  esriLoader.dojoRequire(['esri/arcgis/utils'], (arcgisUtils) => {
    // create a map at a DOM node in this component
    arcgisUtils.createMap(itemId, this.refs.map)
    .then((response) => {
      // hide the loading indicator
      // and show the map title
      // NOTE: this will trigger a rerender
      this.setState({
        mapLoaded: true,
        item: response.itemInfo.item
      })
    })
  })
}

The benefit of using esri-loader over the approach shown above is that you don't have to use the Dojo loader and toolchain to load and build your entire application. You can use the React toolchain of your choice (webpack, etc).

This blog post explains how this approach works and compares it to other (similar) approaches used in applications like esri-redux.

Gummy answered 2/12, 2016 at 2:58 Comment(2)
FYI, you don't need to lazy load the ArcGIS API when using esri-loader. Instead, you can load the ArcGIS API via a script tag in index.html like so <script src="//js.arcgis.com/3.18compact/"></script>. In this case, the above code for componentDidMount() would simply be this._createMap().Gummy
Can you please help me out to display popup or info window on click of marker location here at #69631372Maine
A
-1

You don't need to import esri api like you do for ReactJS. As the react file will finally compile into a js file you need to write the esri parts as it is and mix the ReactJS part for handling the dom node, which is the main purpose of ReactJS.

A sample from the links below is here

define([  
   'react',  
   'esri/toolbars/draw',  
   'esri/geometry/geometryEngine',  
   'dojo/topic',  
   'dojo/on',  
   'helpers/NumFormatter'  
 ], function(  
   React,  
   Draw, geomEngine,  
   topic, on,  
   format  
 ) {  
  var fixed = format(3);  
  var DrawToolWidget = React.createClass({  
    getInitialState: function() {  
       return {  
         startPoint: null,  
         btnText: 'Draw Line',  
         distance: 0,  
         x: 0,  
         y: 0  
       };  
     },  
     componentDidMount: function() {  
      this.draw = new Draw(this.props.map);  
      this.handler = this.draw.on('draw-end', this.onDrawEnd);  
      this.subscriber = topic.subscribe(  
        'map-mouse-move', this.mapCoordsUpdate  
       );  
     },  
     componentWillUnMount: function() {  
       this.handler.remove();  
       this.subscriber.remove();  
     },  
     onDrawEnd: function(e) {  
       this.draw.deactivate();  
       this.setState({  
       startPoint: null,  
         btnText: 'Draw Line'  
       });  
    },  
    mapCoordsUpdate: function(data) {  
      this.setState(data);  
      // not sure I like this conditional check  
      if (this.state.startPoint) {  
        this.updateDistance(data);  
      }  
    },  
    updateDistance: function(endPoint) {  
      var distance = geomEngine.distance(this.state.startPoint, endPoint);  
      this.setState({ distance: distance });  
    },  
    drawLine: function() {  
      this.setState({ btnText: 'Drawing...' });  
      this.draw.activate(Draw.POLYLINE);  
      on.once(this.props.map, 'click', function(e) {  
         this.setState({ startPoint: e.mapPoint });  
         // soo hacky, but Draw.LINE interaction is odd to use  
        on.once(this.props.map, 'click', function() {  
          this.onDrawEnd();  
        }.bind(this));  
      }.bind(this))  
    },  
    render: function() {  
      return (  
        <div className='well'>  
          <button className='btn btn-primary' onClick={this.drawLine}>  
            {this.state.btnText}  
          </button>  
          <hr />  
          <p>  
             <label>Distance: {fixed(this.state.distance)}</label>  
          </p>  
        </div>  
       );  
     }  
  });  
  return DrawToolWidget;  
});  

Below are the links where you can find information in detail.

http://odoe.net/blog/esrijs-reactjs/

https://geonet.esri.com/people/odoe/blog/2015/04/01/esrijs-with-reactjs-updated

Amaryl answered 12/10, 2016 at 13:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.