├── .babelrc ├── .gitignore ├── README.md ├── package.json ├── public ├── assets │ └── favicon.ico └── index.html ├── src ├── components │ └── WebMap.js ├── config.js ├── css │ ├── index.scss │ └── main.scss ├── data │ └── app.js └── index.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { 4 | "useBuiltIns": "entry", 5 | "targets": "> 0.25%, not ie 11, not dead, not op_mini all", 6 | "modules":"amd" 7 | }], 8 | "@babel/preset-react" 9 | ], 10 | "plugins": [ 11 | "@babel/proposal-class-properties", 12 | "@babel/proposal-object-rest-spread", 13 | "@babel/plugin-syntax-dynamic-import" 14 | ] 15 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | .vscode/* 3 | build/* 4 | dist/* 5 | html-report/* 6 | ~tmp/* 7 | .baseDir* 8 | .tsdrc 9 | .tscache 10 | npm-debug.log 11 | yarn.lock 12 | package-lock.json 13 | coverage-final.* 14 | .firebaserc 15 | firebase.json 16 | firebase-debug.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ArcGIS API for JavaScript with React 2 | 3 | This is a sample application of using the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/) with [React](https://reactjs.org/). 4 | 5 | ## Build 6 | 7 | `npm run build` 8 | 9 | ## Development 10 | 11 | `npm start` 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsapi-react", 3 | "version": "1.0.0", 4 | "description": "Sample application using the ArcGIS API for JavaScript with React", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "start": "webpack-dev-server --history-api-fallback --mode development --open", 8 | "build": "webpack --mode production", 9 | "serve": "webpack-dev-server --history-api-fallback --mode production --open --https --compress" 10 | }, 11 | "keywords": [ 12 | "react", 13 | "arcgis", 14 | "gis", 15 | "geodev", 16 | "spatial" 17 | ], 18 | "author": "", 19 | "license": "Apache-2.0", 20 | "dependencies": { 21 | "@arcgis/webpack-plugin": "~4.10.5", 22 | "react": "^16.8.2", 23 | "react-dom": "^16.8.2", 24 | "styled-components": "^4.1.1" 25 | }, 26 | "devDependencies": { 27 | "@babel/core": "^7.1.6", 28 | "@babel/plugin-proposal-class-properties": "^7.1.0", 29 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0", 30 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 31 | "@babel/preset-env": "^7.1.6", 32 | "@babel/preset-react": "^7.0.0", 33 | "@types/arcgis-js-api": "~4.10.0", 34 | "@types/react": "^16.8.2", 35 | "@types/react-dom": "^16.0.7", 36 | "@types/styled-components": "^4.1.0", 37 | "babel-loader": "^8.0.4", 38 | "babel-plugin-styled-components": "^1.8.0", 39 | "clean-webpack-plugin": "^0.1.19", 40 | "copy-webpack-plugin": "^4.6.0", 41 | "css-loader": "^0.28.11", 42 | "html-loader": "^0.5.5", 43 | "html-webpack-inline-source-plugin": "^0.0.10", 44 | "html-webpack-plugin": "^3.1.0", 45 | "mini-css-extract-plugin": "^0.4.0", 46 | "node-sass": "~4.9.4 ", 47 | "optimize-css-assets-webpack-plugin": "^4.0.1", 48 | "prettier": "^1.15.2", 49 | "resolve-url-loader": "^2.3.0", 50 | "sass-loader": "^6.0.7", 51 | "style-loader": "0.20.3", 52 | "ts-jest": "^23.10.4", 53 | "uglifyjs-webpack-plugin": "^1.2.5", 54 | "webpack": "^4.25.1", 55 | "webpack-cli": "^3.1.1", 56 | "webpack-dev-server": "^3.1.10" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /public/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odoe/jsapi-react/dcb6376e81af64f051c83a8d0062f82c8a8efcf6/public/assets/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ArcGIS React Sample 9 | 10 | 11 | 12 |
13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/WebMap.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from "react"; 2 | 3 | export function WebMap() { 4 | const elementRef = useRef(); 5 | 6 | useEffect(_ => { 7 | let cleanup; 8 | // lazy load the module that loads the JSAPI 9 | // and initialize it 10 | import("../data/app").then( 11 | app => cleanup = app.initialize(elementRef.current) 12 | ); 13 | return () => cleanup && cleanup(); 14 | }, []); 15 | 16 | // assign elementRef to the ref of our component 17 | return ( 18 |
19 |
20 | ); 21 | } 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | import "@dojo/framework/shim/Promise"; 2 | import esriConfig from "esri/config"; 3 | 4 | const DEFAULT_WORKER_URL = "https://js.arcgis.com/4.10/"; 5 | const DEFAULT_LOADER_URL = `${DEFAULT_WORKER_URL}dojo/dojo-lite.js`; 6 | 7 | esriConfig.workers.loaderUrl = DEFAULT_LOADER_URL; 8 | esriConfig.workers.loaderConfig = { 9 | baseUrl: `${DEFAULT_WORKER_URL}dojo`, 10 | packages: [ 11 | { name: "esri", location: DEFAULT_WORKER_URL + "esri" }, 12 | { name: "dojo", location: DEFAULT_WORKER_URL + "dojo" }, 13 | { name: "dojox", location: DEFAULT_WORKER_URL + "dojox" }, 14 | { name: "dijit", location: DEFAULT_WORKER_URL + "dijit" }, 15 | { name: "dstore", location: DEFAULT_WORKER_URL + "dstore" }, 16 | { name: "moment", location: DEFAULT_WORKER_URL + "moment" }, 17 | { name: "@dojo", location: DEFAULT_WORKER_URL + "@dojo" }, 18 | { 19 | name: "cldrjs", 20 | location: DEFAULT_WORKER_URL + "cldrjs", 21 | main: "dist/cldr" 22 | }, 23 | { 24 | name: "globalize", 25 | location: DEFAULT_WORKER_URL + "globalize", 26 | main: "dist/globalize" 27 | }, 28 | { 29 | name: "maquette", 30 | location: DEFAULT_WORKER_URL + "maquette", 31 | main: "dist/maquette.umd" 32 | }, 33 | { 34 | name: "maquette-css-transitions", 35 | location: DEFAULT_WORKER_URL + "maquette-css-transitions", 36 | main: "dist/maquette-css-transitions.umd" 37 | }, 38 | { 39 | name: "maquette-jsx", 40 | location: DEFAULT_WORKER_URL + "maquette-jsx", 41 | main: "dist/maquette-jsx.umd" 42 | }, 43 | { name: "tslib", location: DEFAULT_WORKER_URL + "tslib", main: "tslib" } 44 | ] 45 | }; -------------------------------------------------------------------------------- /src/css/index.scss: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | width: 100%; 6 | height: 100%; 7 | font-feature-settings: "liga" 1, "calt" 0; 8 | } 9 | 10 | #root, .viewDiv { 11 | padding: 0; 12 | margin: 0; 13 | width: 100%; 14 | height: 100%; 15 | display: flex; 16 | letter-spacing: 0em; 17 | line-height: 1.55rem; 18 | } 19 | -------------------------------------------------------------------------------- /src/css/main.scss: -------------------------------------------------------------------------------- 1 | $image-path: "~calcite-web/dist/img" !default; 2 | $font-path: "~calcite-web/dist/fonts" !default; 3 | 4 | $icomoon-font-path: "~arcgis-js-api/themes/base/icons/fonts" !default; 5 | 6 | // Widgets (sorted alphabetically) 7 | $include_AreaMeasurement3D: false !default; 8 | $include_Attribution: true !default; 9 | $include_BasemapGallery: false !default; 10 | $include_BasemapToggle: false !default; 11 | $include_Bookmarks: false !default; 12 | $include_BrowseItems: false !default; 13 | $include_ColorPicker: false !default; 14 | $include_Compass: true !default; 15 | $include_CoordinateConversion: false !default; 16 | $include_DatePicker: false !default; 17 | $include_Directions: false !default; 18 | $include_Expand: false !default; 19 | $include_Feature: false !default; 20 | $include_FeatureForm: false !default; 21 | $include_HorizontalSlider: false !default; 22 | $include_LayerList: false !default; 23 | $include_Legend: false !default; 24 | $include_NavigationToggle: false !default; 25 | $include_Print: false !default; 26 | $include_DirectLineMeasurement3D: false !default; 27 | $include_Popup: true !default; 28 | $include_RasterSymbologyEditor: false !default; 29 | $include_RendererSlider: false !default; 30 | $include_ScaleBar: false !default; 31 | $include_Search: true !default; 32 | $include_Slice: false !default; 33 | $include_Spinner: true !default; 34 | $include_Tags: false !default; 35 | $include_FeatureTemplates: false !default; 36 | $include_TimePicker: false !default; 37 | $include_Zoom: true !default; 38 | 39 | @import "~arcgis-js-api/themes/light/main.scss"; 40 | @import "index"; -------------------------------------------------------------------------------- /src/data/app.js: -------------------------------------------------------------------------------- 1 | import WebMap from "esri/WebMap"; 2 | import MapView from "esri/views/MapView"; 3 | import Search from "esri/widgets/Search"; 4 | 5 | const noop = () => {}; 6 | 7 | export const webmap = new WebMap({ 8 | portalItem: { 9 | id: "974c6641665a42bf8a57da08e607bb6f" 10 | } 11 | }); 12 | 13 | export const view = new MapView({ 14 | map: webmap 15 | }); 16 | 17 | export const search = new Search({ view }); 18 | view.ui.add(search, "top-right"); 19 | 20 | export const initialize = (container) => { 21 | view.container = container; 22 | view 23 | .when() 24 | .then(_ => { 25 | console.log("Map and View are ready"); 26 | }) 27 | .catch(noop); 28 | return () => { 29 | view.container = null; 30 | }; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import "./config"; 2 | 3 | import React from "react"; 4 | import { render } from "react-dom"; 5 | 6 | import { WebMap } from "./components/WebMap"; 7 | 8 | const rootElement = document.getElementById("root"); 9 | render(, rootElement); 10 | 11 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const ArcGISPlugin = require("@arcgis/webpack-plugin"); 2 | const CleanWebpackPlugin = require("clean-webpack-plugin"); 3 | const HtmlWebPackPlugin = require("html-webpack-plugin"); 4 | const HtmlWebpackInlineSourcePlugin = require("html-webpack-inline-source-plugin"); 5 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 6 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 7 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); 8 | 9 | const path = require("path"); 10 | const webpack = require("webpack"); 11 | 12 | module.exports = function(_, arg) { 13 | const config = { 14 | entry: { 15 | index: ["./src/css/main.scss", "./src/index.js"] 16 | }, 17 | output: { 18 | filename: "[name].[chunkhash].js", 19 | publicPath: "" 20 | }, 21 | optimization: { 22 | minimizer: [ 23 | new UglifyJsPlugin({ 24 | uglifyOptions: { 25 | output: { 26 | comments: false 27 | } 28 | }, 29 | cache: true, 30 | parallel: true, 31 | sourceMap: false 32 | }), 33 | new OptimizeCSSAssetsPlugin({ 34 | cssProcessorOptions: { 35 | discardComments: { 36 | removeAll: true 37 | }, 38 | // Run cssnano in safe mode to avoid 39 | // potentially unsafe transformations. 40 | safe: true 41 | } 42 | }) 43 | ] 44 | }, 45 | module: { 46 | rules: [ 47 | { 48 | exclude: /node_modules/, 49 | test: /\.js?$/, 50 | loader: "babel-loader" 51 | }, 52 | { 53 | test: /\.html$/, 54 | use: [ 55 | { 56 | loader: "html-loader", 57 | options: { minimize: false } 58 | } 59 | ], 60 | exclude: /node_modules/ 61 | }, 62 | { 63 | test: /\.(jpe?g|png|gif|svg|webp)$/, 64 | loader: "url-loader", 65 | options: { 66 | // Inline files smaller than 10 kB (10240 bytes) 67 | limit: 10 * 1024 68 | } 69 | }, 70 | { 71 | test: /\.(wsv|ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/, 72 | use: [ 73 | { 74 | loader: "file-loader", 75 | options: { 76 | name: "build/[name].[ext]" 77 | } 78 | } 79 | ] 80 | }, 81 | { 82 | test: /\.css$|\.scss$/, 83 | use: [ 84 | MiniCssExtractPlugin.loader, 85 | "css-loader", 86 | { 87 | loader: "resolve-url-loader", 88 | options: { includeRoot: true } 89 | }, 90 | { 91 | loader: "sass-loader", 92 | options: { 93 | sourceMap: true, 94 | includePaths: [ 95 | path.resolve("./node_modules") 96 | ] 97 | } 98 | } 99 | ] 100 | } 101 | ] 102 | }, 103 | plugins: [ 104 | new webpack.DefinePlugin({ 105 | "process.env.NODE_ENV": JSON.stringify(arg.mode || "production") 106 | }), 107 | 108 | new CleanWebpackPlugin(["dist"]), 109 | 110 | new ArcGISPlugin({ 111 | useDefaultAssetLoaders: false 112 | }), 113 | 114 | new HtmlWebPackPlugin({ 115 | template: "./public/index.html", 116 | filename: "./index.html", 117 | favicon: "./public/assets/favicon.ico", 118 | chunksSortMode: "none", 119 | inlineSource: ".(css)$", 120 | mode: arg.mode 121 | }), 122 | 123 | new MiniCssExtractPlugin({ 124 | filename: "[name].[chunkhash].css", 125 | chunkFilename: "[id].css" 126 | }), 127 | 128 | new HtmlWebpackInlineSourcePlugin() 129 | ], 130 | resolve: { 131 | modules: [ 132 | path.resolve(__dirname, "/src"), 133 | path.resolve(__dirname, "node_modules/") 134 | ], 135 | extensions: [".js", ".scss", ".css"] 136 | }, 137 | node: { 138 | process: false, 139 | global: false, 140 | fs: "empty" 141 | } 142 | }; 143 | 144 | return config; 145 | }; 146 | --------------------------------------------------------------------------------