slutske22 / react-esri-leaflet Goto Github PK
View Code? Open in Web Editor NEWreact components for esri-leaflet
Home Page: https://codesandbox.io/s/github/slutske22/react-esri-leaflet/tree/master/examples/ts
License: MIT License
react components for esri-leaflet
Home Page: https://codesandbox.io/s/github/slutske22/react-esri-leaflet/tree/master/examples/ts
License: MIT License
Are there plans to support Feature Layers utilizing the symbology they are published with?
This is taken care of the Esri Leaflet Renderers plugin in non-React environments.
Perhaps related to this issue, I'm having some issues with refs andTiledMapLayer. Minimal example of my code is below:
import React from 'react';
import { MapContainer, TileLayer, ZoomControl } from 'react-leaflet'
import { TiledMapLayer } from 'react-esri-leaflet';
import { TiledMapLayer as EsriTiledMapLayer } from 'esri-leaflet';
import { LatLngBoundsExpression, LatLngTuple, Map as LeafletMap, TileLayer as LeafletTileLayer } from 'leaflet';
import bbox from '@turf/bbox';
import "./Map.css";
import { useTrackedState } from '../../state';
export default function Map() {
const state = useTrackedState();
const [map, setMap] = React.useState<LeafletMap>();
const esriLayerRef= React.useRef<EsriTiledMapLayer>(null);
const bboxArray = bbox(JSON.parse(state.features));
const corner1: LatLngTuple = [bboxArray[1], bboxArray[0]];
const corner2: LatLngTuple = [bboxArray[3], bboxArray[2]];
const bounds: LatLngBoundsExpression = [corner1, corner2];
/** if panel is collapsed, reset the map and tile layer **/
React.useEffect(() => {
let tileLayer = esriLayerRef.current;
if (map && tileLayer) {
map.invalidateSize();
tileLayer.redraw();
}
}, [state.panelCollapsed]);
return (
<MapContainer bounds={bounds} id="projectMap" zoomControl={false} whenCreated={setMap}>
<TiledMapLayer
ref={navLayerRef}
maxNativeZoom={10} url="https://server.arcgisonline.com/ArcGIS/rest/services/the/layer"
/>
<ZoomControl position='topright' />
</MapContainer>
);
}
Perhaps my tsconfig is too strict...but I'm receiving the following error:
Type 'RefObject<TiledMapLayer>' is not assignable to type 'Ref<RefObject<TiledMapLayer>> | undefined'.
Type 'RefObject<TiledMapLayer>' is not assignable to type 'RefObject<RefObject<TiledMapLayer>>'.
Property 'current' is missing in type 'TiledMapLayer' but required in type 'RefObject<TiledMapLayer>'.ts(2322)
[index.d.ts(81, 18): ]()'current' is declared here.
[index.d.ts(133, 9): ]()The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & TiledMapLayerOptions & RefAttributes<RefObject<TiledMapLayer>>'
Is there something going on with the way forwardRef is being used? Let me know if there's any more information I can provide.
Thanks -- and great work on this project!
Hi,
I am trying to remove FeatureLayer added to Map onChnage of Checkbox.
Please help me how can I do this.
I have an application with components in the following basic structure:
<MapContainer>
<BasemapLayer name={mapType} />
</MapContainer>
In this case, mapType
is created via useState()
.
I want to be able to change mapType
(e.g., via a UI control) and have the basemap layer re-draw with the new layer.
However, when I try this, the basemap layer never updates, staying the same as it was when it started.
I made a minimal example of the problem here: https://codesandbox.io/s/prod-shadow-xokzy3?file=/src/App.tsx
I am very unfamiliar with React, so this is probably user error, but I'm not sure the best way to work around this issue.
This is not a problem per se with your code, but your code could possibly solve the bug in other code. (Or if you wish, I could take this to the esri-leaflet people.)
What happens is that each time you call identify, esri-leaflet creates a new jsonp callback script element. This continues ad infinitum. A quick solution is to capture the returned script id and immediately remove the element, as shown below. (This is okay, as the initial script include has already fired off the request. Another method is to remove it in your own callback.)
{
let idInfo = myLayer.current.identify()
.layers(layerParam)
.tolerance(16)
.on(theMap)
.at(ev.latlng)
.run(function(error:any, featureCollection:any, response:any)
{
if (response != undefined)
{
listItems(response.results);
}
});
// delete the callback jsonp script
if (idInfo && idInfo.id)
document.getElementById(idInfo.id).remove();
}
This way, the DOM does not get filled up with old identify scripts. Another possiblity might be to somehow capture this method in your code and do the deletion for the user (??).
In any case, your users should be made aware of this, possibly by including a note or code in your examples.
Thanks again!
Kev
Running into an issue with testing with mocha
, where the code in the build
folder contains ES6 style imports and causes tests to fail with:
$ mocha --recursive --extension=js,cjs,mjs,jsx -r @babel/register -r jsdom-global/register -r ignore-styles 'src/**/*.test.jsx'
/home/user/my-repo/node_modules/react-esri-leaflet/build/index.js:1
import EsriLeafletLayer from './EsriLeafletLayer';
^^^^^^
SyntaxError: Cannot use import statement outside a module
After cloning react-esri-leaflet
and messing around with it, I found that adding --extensions \".tsx\"
to transpile:main
and using the build
generated by that command allows the tests to function.
Is it intended that the code in the build
folder contains non-transpiled output?
Sorry if this question makes no sense. I was wondering if there is an example of this package rendering WMTS data? I tried searching around but couldn't find any concrete examples.
Hi, I'm trying to give a UI to allow the user to modify the default where clause in a <FeatureLayer/>
I have not yet figured out how to make the map rerender properly after the variables in the where clause change.
I'm passing in the year as a prop to this functional component - and that does update the where clause - but the layer disappears from the <MapContainer/>
and I am getting a 400 error about the query not being able to execute. If I trigger a re-render of the entire <TheMap/>
component then it works. Was reading code doc for the setWhere
* Sets the new where option and refreshes the layer to reflect the new where filter. Accepts an optional
* callback and function context.
*/
setWhere(where: string, callback?: FeatureCallbackHandler, context?: any): this;
/**
Here is a snippet of what I'm currently doing. I may simply not understand react and re-rendering flow.
const TheMap = ({ year }) => {
return (
<MapContainer
id="mapId"
style={mapstyle}
zoom={zoom}
center={{ lat: lat, lng: lon }}
>
<MapEvents />
<LayersControl position="topleft" collapsed={false}>
<LayersControl.Overlay name="Point Defects" checked>
<FeatureLayer
cacheLayers={false}
where={`pr > 1 AND setup_id LIKE '${year}%'`}
pointToLayer={function (features) {
return L.marker(features.geometry.coordinates.reverse(), {
icon: makeIcon(colors[features.properties.pr], 4, "black", 30),
});
}}
url="{featureServiceURL}",
eventHandlers={{
loading: () => console.log("loading features"),
load: () => console.log("featurelayer loaded"),
}}
/>
</LayersControl.Overlay>
</LayersControl>
</MapContainer>
)
}
When in development environment, the VectorBasemapLayer
works as advertised. I am able to select the different basemaps to include with and without labels.
However, once in production environment, I am only getting the base layers with no overlays on top (labels, coloring, etc...).
The Dev console throws an uncaught reference error that y
is not defined.
Have any of you run into this issue using your latest version? Wondering how you might have resolved it.
Some Context...
I have react, react-dom, leaflet, react-leaflet, esri-leaflet already installed (see below for all package.json list). Then when I try to install react-esri-leaflet I get some dependency errors (see below for error output in terminal).
For reference, I am using the basic Create React App setup.
--- Error when npm install react-esri-leaflet ---
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/esri-leaflet
npm ERR! esri-leaflet@"^3.0.1" from the root project
npm ERR! peer esri-leaflet@"^3.0.1" from [email protected]
npm ERR! node_modules/react-esri-leaflet
npm ERR! react-esri-leaflet@"" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer esri-leaflet@"^2.3.0" from [email protected]
npm ERR! node_modules/esri-leaflet-vector
npm ERR! peer esri-leaflet-vector@"^3.0.0" from [email protected]
npm ERR! node_modules/react-esri-leaflet
npm ERR! react-esri-leaflet@"" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
--- From my Package.json ---
"dependencies": {
"@emotion/css": "^11.1.3",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"esri-leaflet": "^3.0.1",
"leaflet": "^1.7.1",
"lodash.every": "^4.6.0",
"lodash.filter": "^4.6.0",
"lodash.get": "^4.4.2",
"lodash.has": "^4.5.2",
"lodash.pick": "^4.4.0",
"lodash.set": "^4.3.2",
"lodash.unset": "^4.5.2",
"mobx": "^6.3.0",
"mobx-react-lite": "^3.2.0",
"nanoid": "^3.1.22",
"page": "^1.11.6",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.2.0",
"react-leaflet": "^3.1.0",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
}
Results in event "results" are different than the results shown in the "geocoder-control-suggestions".
These are the results when I type in "Botter,":
The "response.suggestions" in the "requestsuccess" function is always an empty array.
But it does fill the "geocoder-control-suggestions" with correct suggestions.
When I press enter, the "results" event returns an array of 4 items, which were not shown in the "suggestions".
This is the object which is returned in the "results" event:
[
{
"text": "De Botter",
"bounds": {
"_southWest": {
"lat": 52.29370000000005,
"lng": 5.229480000000076
},
"_northEast": {
"lat": 52.303700000000056,
"lng": 5.239480000000076
}
},
"score": 97.75,
"latlng": {
"lat": 52.29870000000005,
"lng": 5.234480000000076
},
"properties": {
"Loc_name": "World",
"Status": "T",
"Score": 97.75,
"Match_addr": "De Botter",
"LongLabel": "De Botter, Havenstraat 15, 1271 AB Huizen, NLD",
"ShortLabel": "De Botter",
"Addr_type": "POI",
"Type": "Bar or Pub",
"PlaceName": "De Botter",
"Place_addr": "Havenstraat 15, 1271 AB Huizen",
"StName": "Havenstraat",
"StAddr": "Havenstraat 15",
"Postal": "1271 AB",
"Country": "NLD",
"CntryName": "Nederland",
"LangCode": "DUT"
}
},
{
"text": "De Botter",
"bounds": {
"_southWest": {
"lat": 51.86031000000008,
"lng": 4.614950000000074
},
"_northEast": {
"lat": 51.87031000000008,
"lng": 4.624950000000074
}
},
"score": 97.75,
"latlng": {
"lat": 51.86531000000008,
"lng": 4.619950000000074
},
"properties": {
"Loc_name": "World",
"Status": "T",
"Score": 97.75,
"Match_addr": "De Botter",
"LongLabel": "De Botter, Voorn 11, 2986 JA Ridderkerk, NLD",
"ShortLabel": "De Botter",
"Addr_type": "POI",
"Type": "School",
"PlaceName": "De Botter",
"Place_addr": "Voorn 11, 2986 JA Ridderkerk",
"StName": "Voorn",
"StAddr": "Voorn 11",
"Postal": "2986 JA",
"Country": "NLD",
"CntryName": "Nederland",
"LangCode": "DUT"
}
},
{
"text": "De Botter",
"bounds": {
"_southWest": {
"lat": 52.34574000000003,
"lng": 5.610380000000073
},
"_northEast": {
"lat": 52.35574000000003,
"lng": 5.620380000000073
}
},
"score": 97.75,
"latlng": {
"lat": 52.35074000000003,
"lng": 5.615380000000073
},
"properties": {
"Loc_name": "World",
"Status": "T",
"Score": 97.75,
"Match_addr": "De Botter",
"LongLabel": "De Botter, Strandboulevard West, 3841 CS Harderwijk, NLD",
"ShortLabel": "De Botter",
"Addr_type": "POI",
"Type": "International Food",
"PlaceName": "De Botter",
"Place_addr": "Strandboulevard West, 3841 CS Harderwijk",
"StName": "Strandboulevard West",
"StAddr": "Strandboulevard West",
"Postal": "3841 CS",
"Country": "NLD",
"CntryName": "Nederland",
"LangCode": "DUT"
}
},
{
"text": "De Botter",
"bounds": {
"_southWest": {
"lat": 52.78139000000004,
"lng": 5.836760000000022
},
"_northEast": {
"lat": 52.79139000000004,
"lng": 5.846760000000022
}
},
"score": 97.75,
"latlng": {
"lat": 52.78639000000004,
"lng": 5.841760000000022
},
"properties": {
"Loc_name": "World",
"Status": "T",
"Score": 97.75,
"Match_addr": "De Botter",
"LongLabel": "De Botter, Burchtstraat 3, 8374 KC Kuinre, NLD",
"ShortLabel": "De Botter",
"Addr_type": "POI",
"Type": "Bar or Pub",
"PlaceName": "De Botter",
"Place_addr": "Burchtstraat 3, 8374 KC Kuinre",
"StName": "Burchtstraat",
"StAddr": "Burchtstraat 3",
"Postal": "8374 KC",
"Country": "NLD",
"CntryName": "Nederland",
"LangCode": "DUT"
}
}
]
I removed some of the unnecessary properties.
My code:
<EsriLeafletGeoSearch
useMapBounds={false}
position={control.position}
allowMultipleResults={true}
expanded={true}
eventHandlers={{
results: (data) => {
// ... me creating a marker for each data result..
}
}}
placeholder={t("Zoeken naar plaatsen of adressen")}
title={t("Locatie zoeken")}
providers={{
arcgisOnlineProvider: {
apikey: ... my apikey,
countries: ["NLD"],
maxResults: 10
}
}}
/>
When I set "AllowMultipleResults" to false, the suggestions stay the same but when I press enter, I receive 0 results.
I also tried setting the "categories" but this has no effect.
In short: the "suggestions" show different results than the actual "results".
Versions:
"esri-leaflet": "3.0.10",
"esri-leaflet-geocoder": "3.1.4",
"esri-leaflet-vector": "4.0.1",
"leaflet": "1.9.3",
"react-esri-leaflet": "2.0.1",
"react-leaflet": "4.2.1"
Thanks
Added a deprecation warning when using L.esri.BasemapLayer (info).
This warning can be disabled by setting the ignoreDeprecationWarning option to true. (Esri/esri-leaflet#1293).
I think it would be interesting to forward that flag on react-esri-leaflet.
First, thanks for the library. One of the examples shows a useRef to get a handle to a layer. However, when I tried that with DynamicLayer so that I could trigger an Identify task later, React of course complained that I could not use refs with such a component.
Am I missing something? Thanks for any help. If this is the wrong venue for such a question, please direct to the right spot. Thank you.
I get this error when using the library (see https://codesandbox.io/s/react-esri-leaflet-v2-forked-b7345). It seems to work fine with version 1.0.3, but every version after gives this error.
Perhaps (probably?) I'm doing something wrong but here is my scenario.
Using the EsriLeafletGeoSearch
plugin, we configure providers
by passing an object who's keys are parsed into the provider type that esri-leaflet-geocoder supports.
so example object looks something like this:
mapServiceProvider: {
token: token,
url: "https://server/server/rest/services/folder/service/MapServer",
layers: [21],
searchFields: ["id"],
label: "Feature X",
searchMode: "strict",
bufferRadius: 10,
maxResults: 20,
formatSuggestion: function (feature) {
return `${feature.properties.id}` || null;
},
},
// mapServiceProvider: {
// token: token,
// url: "https://server/server/rest/services/folder/service/MapServer",
// layers: [3],
// searchFields: ["name", "id"],
// label: "Feature Y",
// searchMode: "startsWith",
// bufferRadius: 10,
// maxResults: 20,
// formatSuggestion: function (feature) {
// return `${feature.properties.id} ${feature.properties.name}` || null;
// },
// },
Since the object is then parsed using Object.keys(object) to tell ELG which provider type we want being one of
It appears to me that one cannot configure 2 or more of the same type of provider this way because you'd have to create an object with duplicate keys and I think the last one in wins.
In the ELG documentation here - it looks like it can support multiple providers of the same type maybe?
https://developers.arcgis.com/esri-leaflet/api-reference/controls/geosearch/#providers
But it looks like it would require us passing in an array of objects so we're not relying on the keys of an object for provider type and instead we use a key/value pair that defines the provider type.
So would that be changing things around here?
Perhaps it would accept something like this example below to configure multiple of the same type of providers?
[
{
"type": "mapServiceProvider",
"options": {
"token": token,
"url": "https://server/server/rest/services/folder/service/MapServer",
"layers": [21],
"searchFields": ["id"],
"label": "Feature X",
"searchMode": "strict",
"bufferRadius": 10,
"maxResults": 20,
"formatSuggestion": function (feature) {
return `${feature.properties.id}` || null;
},
}
},
{
"type": "mapServiceProvider",
"options": {
"token": token,
"url": "https://server/server/rest/services/folder/service/MapServer",
"layers": [3],
"searchFields": ["name", "id"],
"label": "Feature X",
"searchMode": "strict",
"bufferRadius": 10,
"maxResults": 20,
"formatSuggestion": function (feature) {
return `${feature.properties.id} ${feature.properties.name}` || null;
},
}
},
]
Thanks for listening.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.