React ArcGIS项目API Key放置位置及FeatureLayer不显示问题
问题根因
- API Key配置规则:Key不需要单独传给Map或者FeatureLayer组件,只要在初始化逻辑里给
esriConfig.apiKey赋值即可全局生效,底图正常加载已经说明Key配置本身是有效的。 - 模块解构顺序错位:你传入
loadModules的模块列表,和回调里解构的变量顺序不匹配,从esri/layers/GeoJSONLayer开始所有类全部对应错误,你代码里调用的new FeatureLayer()实际拿到的是GraphicsLayer构造函数,根本无法生成正确的FeatureLayer实例。 - 无效DOM操作中断执行:你调用
view.ui.add("infoDiv", "bottom-left")时,JSX里不存在id为infoDiv的元素,这行代码会直接抛出JS错误,中断后续所有FeatureLayer创建、状态更新的逻辑,这就是featureLayer1一直为null显示Empty的直接原因。 - useEffect缺少依赖数组:当前useEffect没有传第二个参数,会在组件每次重渲染时重复执行,触发状态更新→重渲染→重新初始化地图的死循环,即使前面的错误修复,也会导致地图实例反复创建、状态异常覆盖。
修复方案
首先修正模块解构顺序、删除无效DOM操作、给useEffect添加空依赖数组确保地图只初始化一次,同时添加实例销毁逻辑避免内存泄漏,修复后的完整代码如下:
import React, { useEffect, useRef, useState } from "react"; import { loadModules } from "esri-loader"; function Map() { const [featureLayer1, setFeatureLayer1] = useState(null); const viewRef = useRef(null); const MapElement = useRef(null); useEffect(() => { loadModules( [ "esri/views/MapView", "esri/Map", "esri/config", "esri/layers/GeoJSONLayer", "esri/Graphic", "esri/layers/GraphicsLayer", "esri/layers/FeatureLayer", "esri/renderers/SimpleRenderer", "esri/symbols/SimpleFillSymbol", "esri/widgets/Legend", ], { css: true, } ).then( ([ MapView, Map, esriConfig, GeoJSONLayer, Graphic, GraphicsLayer, FeatureLayer, SimpleRenderer, SimpleFillSymbol, Legend, ]) => { const houseStatus = { Unreleased: [99, 97, 97], Sold: [255, 0, 0], Available: [0, 255, 0], Other: [0, 0, 255], }; esriConfig.apiKey = "MY_API_KEY"; const map = new Map({ basemap: "arcgis-imagery", }); const view = new MapView({ map: map, center: [18.9660638, -33.8071444], zoom: 13, container: MapElement.current, }); viewRef.current = view; const graphicsLayer = new GraphicsLayer(); graphicsLayer.opacity = 0.5; map.add(graphicsLayer); const streetLayer = new FeatureLayer({ url: "https://services5.arcgis.com/WPkXI1mQdYLzFttB/arcgis/rest/services/Navigation_Barriers/FeatureServer/0", }); // 捕获图层加载错误方便排查 streetLayer.when(() => { setFeatureLayer1(streetLayer); }).catch(err => console.error("streetLayer加载失败:", err)); const erfLayer = new FeatureLayer({ url: "https://services5.arcgis.com/WPkXI1mQdYLzFttB/arcgis/rest/services/VdV_Cadastral/FeatureServer/0", }); const valdevieLabels = { symbol: { type: "text", color: "#FFFFFF", haloColor: "#5E8D74", haloSize: "2px", font: { size: "12px", family: "Noto Sans", style: "italic", weight: "normal", }, }, labelPlacement: "center-center", labelExpressionInfo: { expression: "$feature.Label", }, }; const dotLayer = new FeatureLayer({ url: "https://services5.arcgis.com/WPkXI1mQdYLzFttB/arcgis/rest/services/Greater_VdV_Addresses/FeatureServer/0", labelingInfo: [valdevieLabels], }); dotLayer.opacity = 0; let symbol = { type: "simple-fill", color: [51, 51, 204, 0.9], style: "none", outline: { color: "black", width: 1, }, }; const erfLayerRenderer = { type: "simple", symbol: symbol, }; erfLayer.renderer = erfLayerRenderer; map.add(streetLayer); map.add(dotLayer); map.add(erfLayer); } ); // 组件卸载时销毁地图实例,防止内存泄漏 return () => { if (viewRef.current) { viewRef.current.destroy(); } } // 空依赖数组,确保只在组件挂载时执行一次初始化 }, []); return ( <> <div style={{ height: 800 }} ref={MapElement}> {featureLayer1 !== null ? "Not empty" : "Empty"} </div> </> ); } export default Map;
注意事项
- 用esri-loader对接ArcGIS JS API时,
loadModules的模块列表顺序必须和解构的变量顺序严格一一对应,否则会出现类引用错误,这类问题可以直接在浏览器控制台看到明确的类型报错。 - 所有对DOM的操作要确保对应元素已经渲染,不要引用不存在的DOM节点,否则会中断JS执行流程。
- React的useEffect做一次性初始化逻辑时,必须传空数组作为第二个参数,否则会重复执行逻辑引发异常。
内容的提问来源于stack exchange,提问作者Jacobus Jacobs
相关产品推荐
相关产品推荐

