react-leaflet-vectorgrid
react-leaflet-vectorgrid copied to clipboard
Use with react-leaflet 3.0
Hello there! I am trying to use react-leaflet-vectorgrid with react-leaflet 3.0. It doesn't work because in version 3.0 HOC 'withLeaflet' anymore doesn't exist. Who can help?
+1
I also have a need for this, anyone have any advice?
https://codesandbox.io/s/gracious-fog-9d52v?file=/src/vector-grid.js
@EGNKupava thank you, I will check it out.
I start to port the original code to react-leaflet 3.0 and it work 90%, but for an unknown reason (I'm not familiar enough with React Hooks yet), the active state don't seem to work so the active state is not persistent (active is always null in clearHighlight()
If somebody want to correct that code, they're welcome!
import React, { useState } from 'react';
import { createTileLayerComponent, updateGridLayer } from '@react-leaflet/core';
import L from 'leaflet';
import isObject from 'lodash/isObject';
import isFunction from 'lodash/isFunction';
import isString from 'lodash/isString';
import isEmpty from 'lodash/isEmpty';
import clone from 'lodash/clone';
import cloneDeep from 'lodash/cloneDeep';
import extend from 'lodash/extend';
import merge from 'lodash/merge';
import has from 'lodash/has';
import find from 'lodash/find';
import 'leaflet.vectorgrid';
export const VectorGrid = createTileLayerComponent (
function createTileLayer(props, context) {
const [highlight, setHighlight] = useState(null);
const [active, setActive] = useState(null);
const {
data,
style,
hoverStyle,
activeStyle,
onClick,
onMouseover,
onMouseout,
onDblclick,
onContextmenu,
vectorTileLayerStyles,
url,
maxNativeZoom,
subdomains,
accessKey,
accessToken,
type = 'protobuf',
interactive = true,
idField = '',
...rest
} = props;
delete(rest.leaflet);
const baseStyle = (properties, zoom) => {
if (isFunction(style)) {
return style(properties);
} else if (isObject(style)) {
return style;
}
return {
weight: 0.5,
opacity: 1,
color: '#ccc',
fillColor: '#390870',
fillOpacity: 0.6,
fill: true,
stroke: true
};
};
const _getFeatureId = (feature) => {
const {
idField
} = props;
if (isFunction(idField)) {
return idField(feature);
} else if (isString(idField)) {
return feature.properties[idField];
}
}
const setFeatureStyle = (id, style) => {
vectorGrid.setFeatureStyle(id, style);
}
const resetFeatureStyle = (ids) => {
ids.map((id) => {
vectorGrid.resetFeatureStyle(id);
return null;
});
}
const clearHighlight = (featureId, _active) => {
if (featureId && featureId !== _active) {
resetFeatureStyle([featureId]);
}
if (highlight && highlight !== _active) {
resetFeatureStyle(highlight);
}
setHighlight(null);
}
const clearActive = () => {
if (active) {
resetFeatureStyle(active);
}
setActive(null);
}
const getFeature = (featureId) => {
const {
data,
idField
} = props;
if (isEmpty(data) || isEmpty(data.features)) return {};
const feature = find(data.features, ({
properties
}) => properties[idField] === featureId);
return cloneDeep(feature);
}
const _propagateEvent = (eventHandler, e) =>{
if (!isFunction(eventHandler)) return;
const featureId = _getFeatureId(e.layer);
const feature = getFeature(featureId);
const event = cloneDeep(e);
const mergedEvent = merge(event.target, {
feature
});
eventHandler(event);
}
let vectorGrid;
if (type === 'slicer') {
vectorGrid = new L.vectorGrid.slicer(data, {
interactive: interactive,
getFeatureId: feature => _getFeatureId(feature),
rendererFactory: L.svg.tile,
vectorTileLayerStyles: vectorTileLayerStyles || {
sliced: (properties, zoom) => {
const bs = baseStyle(properties, zoom);
bs.fill = true;
bs.stroke = true;
return bs;
}
},
...rest
});
} else {
vectorGrid = new L.vectorGrid.protobuf(url, {
interactive: interactive,
key: accessKey,
token: accessToken,
vectorTileLayerStyles: vectorTileLayerStyles,
getFeatureId: feature => _getFeatureId(feature),
rendererFactory: L.canvas.tile,
...rest
});
}
vectorGrid.on('mouseover', (e) => {
const {
properties
} = e.layer;
_propagateEvent(onMouseover, e);
let st;
const featureId = _getFeatureId(e.layer);
if (isFunction(hoverStyle)) {
st = hoverStyle(properties);
} else if (isObject(hoverStyle)) {
st = cloneDeep(hoverStyle);
}
if (!isEmpty(st) && featureId) {
clearHighlight();
setHighlight(featureId);
const base = cloneDeep(baseStyle(properties));
const hoverStyle = extend(base, st);
setFeatureStyle(featureId, hoverStyle);
}
})
.on('mouseout', (e) => {
_propagateEvent(onMouseout, e);
const featureId = _getFeatureId(e.layer);
clearHighlight(featureId, active);
})
.on('click', (e) => {
const {
properties
} = e.layer;
const featureId = _getFeatureId(e.layer);
_propagateEvent(onClick, e);
let st;
if (isFunction(activeStyle)) {
st = activeStyle(properties);
} else if (isObject(activeStyle)) {
st = cloneDeep(activeStyle);
}
if (!isEmpty(st) && featureId) {
clearActive();
setActive(featureId);
const base = cloneDeep(baseStyle(properties));
const activeStyle = extend(base, st);
setFeatureStyle(featureId, activeStyle);
}
})
.on('dblclick', (e) => {
_propagateEvent(onDblclick, e);
clearActive();
})
.on('contextmenu', (e) => {
_propagateEvent(onContextmenu, e);
clearActive();
});
return {
instance: vectorGrid,
context
}
},
function upgrade(layer, props, prevprops) {
return updateGridLayer(layer, props, prevprops)
}
)
export default VectorGrid;
I'm fairly certain you need to use a ref, because leaflet maintains its own state. I would look into the useRef hook provided by react
Oh my god, you are right. I really need to invest more time learning React Hooks : I learned React through Class Components and the switch to Function Component is really hard now...
Here's my corrected code that now seems to work 95% : (FYI, I did not port the Popup management code)
import { useRef } from 'react';
import { createTileLayerComponent, updateGridLayer } from '@react-leaflet/core';
import L from 'leaflet';
import isObject from 'lodash/isObject';
import isFunction from 'lodash/isFunction';
import isString from 'lodash/isString';
import isEmpty from 'lodash/isEmpty';
import clone from 'lodash/clone';
import cloneDeep from 'lodash/cloneDeep';
import extend from 'lodash/extend';
import merge from 'lodash/merge';
import has from 'lodash/has';
import find from 'lodash/find';
import 'leaflet.vectorgrid';
export const VectorGrid = createTileLayerComponent (
function createTileLayer(props, context) {
const highlight = useRef(null);
const active = useRef(null);
const {
data,
style,
hoverStyle,
activeStyle,
onClick,
onMouseover,
onMouseout,
onDblclick,
onContextmenu,
vectorTileLayerStyles,
url,
maxNativeZoom,
subdomains,
accessKey,
accessToken,
type = 'protobuf',
interactive = true,
idField = '',
...rest
} = props;
delete(rest.leaflet);
const baseStyle = (properties, zoom) => {
if (isFunction(style)) {
return style(properties);
} else if (isObject(style)) {
return style;
}
return {
weight: 0.5,
opacity: 1,
color: '#ccc',
fillColor: '#390870',
fillOpacity: 0.6,
fill: true,
stroke: true
};
};
const _getFeatureId = (feature) => {
const {
idField
} = props;
if (isFunction(idField)) {
return idField(feature);
} else if (isString(idField)) {
return feature.properties[idField];
}
}
const setFeatureStyle = (id, style) => {
vectorGrid.setFeatureStyle(id, style);
}
const resetFeatureStyle = (id) => {
vectorGrid.resetFeatureStyle(id);
}
const clearHighlight = (properties) => {
if (highlight.current) {
if (highlight.current !== active.current) {
resetFeatureStyle(highlight.current);
} else {
let st;
if (isFunction(activeStyle)) {
st = activeStyle(properties);
} else if (isObject(activeStyle)) {
st = cloneDeep(activeStyle);
}
if (!isEmpty(st)) {
const base = cloneDeep(baseStyle(properties));
const activeStyle = extend(base, st);
setFeatureStyle(active.current, activeStyle);
}
}
}
highlight.current = null;
}
const clearActive = () => {
if (active.current) {
resetFeatureStyle(active.current);
}
active.current = null;
}
const getFeature = (featureId) => {
const {
data,
idField
} = props;
if (isEmpty(data) || isEmpty(data.features)) return {};
const feature = find(data.features, ({
properties
}) => properties[idField] === featureId);
return cloneDeep(feature);
}
const _propagateEvent = (eventHandler, e) =>{
if (!isFunction(eventHandler)) return;
const featureId = _getFeatureId(e.layer);
const feature = getFeature(featureId);
const event = cloneDeep(e);
const mergedEvent = merge(event.target, {
feature
});
eventHandler(event);
}
let vectorGrid;
if (type === 'slicer') {
vectorGrid = new L.vectorGrid.slicer(data, {
interactive: interactive,
getFeatureId: feature => _getFeatureId(feature),
rendererFactory: L.svg.tile,
vectorTileLayerStyles: vectorTileLayerStyles || {
sliced: (properties, zoom) => {
const bs = baseStyle(properties, zoom);
bs.fill = true;
bs.stroke = true;
return bs;
}
},
...rest
});
} else {
vectorGrid = new L.vectorGrid.protobuf(url, {
interactive: interactive,
key: accessKey,
token: accessToken,
vectorTileLayerStyles: vectorTileLayerStyles,
getFeatureId: feature => _getFeatureId(feature),
rendererFactory: L.canvas.tile,
...rest
});
}
vectorGrid.on('mouseover', (e) => {
const {
properties
} = e.layer;
_propagateEvent(onMouseover, e);
let st;
const featureId = _getFeatureId(e.layer);
if (isFunction(hoverStyle)) {
st = hoverStyle(properties);
} else if (isObject(hoverStyle)) {
st = cloneDeep(hoverStyle);
}
if (!isEmpty(st) && featureId) {
clearHighlight(properties);
highlight.current = featureId;
const base = cloneDeep(baseStyle(properties));
const hoverStyle = extend(base, st);
setFeatureStyle(featureId, hoverStyle);
}
})
.on('mouseout', (e) => {
const {
properties
} = e.layer;
_propagateEvent(onMouseout, e);
clearHighlight(properties);
})
.on('click', (e) => {
const {
properties
} = e.layer;
const featureId = _getFeatureId(e.layer);
_propagateEvent(onClick, e);
let st;
if (isFunction(activeStyle)) {
st = activeStyle(properties);
} else if (isObject(activeStyle)) {
st = cloneDeep(activeStyle);
}
if (!isEmpty(st) && featureId) {
clearActive();
active.current = featureId;
const base = cloneDeep(baseStyle(properties));
const activeStyle = extend(base, st);
setFeatureStyle(featureId, activeStyle);
}
})
.on('dblclick', (e) => {
_propagateEvent(onDblclick, e);
clearActive();
})
.on('contextmenu', (e) => {
_propagateEvent(onContextmenu, e);
clearActive();
});
return {
instance: vectorGrid,
context
}
},
function upgrade(layer, props, prevprops) {
return updateGridLayer(layer, props, prevprops)
}
)
export default VectorGrid;
I'm on a roll, I fixed the Tooltip and Popup code: (Thanks to @KoduIsGreat again)
import { useEffect, useRef } from 'react';
import { createTileLayerComponent, updateGridLayer } from '@react-leaflet/core';
import L from 'leaflet';
import isObject from 'lodash/isObject';
import isFunction from 'lodash/isFunction';
import isString from 'lodash/isString';
import isEmpty from 'lodash/isEmpty';
import clone from 'lodash/clone';
import cloneDeep from 'lodash/cloneDeep';
import extend from 'lodash/extend';
import merge from 'lodash/merge';
import has from 'lodash/has';
import find from 'lodash/find';
import leaflet.vectorgrid;
export const VectorGrid = createTileLayerComponent (
function createTileLayer(props, context) {
const highlight = useRef(null);
const active = useRef(null);
const {
data,
style,
hoverStyle,
activeStyle,
onClick,
onMouseover,
onMouseout,
onDblclick,
onContextmenu,
vectorTileLayerStyles,
url,
maxNativeZoom,
subdomains,
accessKey,
accessToken,
type = 'protobuf',
interactive = true,
idField = '',
...rest
} = props;
delete(rest.leaflet);
useEffect(() => {
const {
tooltipClassName = '',
tooltip = null,
popup = null
} = props;
if (tooltip) {
vectorGrid.bindTooltip((layer) => {
if (isFunction(tooltip)) {
return tooltip(layer);
} else if (isString(tooltip) && has(layer.properties, tooltip)) {
return String(layer.properties[tooltip]);
} else if (isString(tooltip)) {
return tooltip;
}
return '';
}, {
sticky: true,
direction: 'auto',
className: tooltipClassName
});
}
if (popup) {
vectorGrid.bindPopup(popup);
}
}, [props.tooltip, props.popup]);
const baseStyle = (properties, zoom) => {
if (isFunction(style)) {
return style(properties);
} else if (isObject(style)) {
return style;
}
return {
weight: 0.5,
opacity: 1,
color: '#ccc',
fillColor: '#390870',
fillOpacity: 0.6,
fill: true,
stroke: true
};
};
const _getFeatureId = (feature) => {
const {
idField
} = props;
if (isFunction(idField)) {
return idField(feature);
} else if (isString(idField)) {
return feature.properties[idField];
}
}
const setFeatureStyle = (id, style) => {
vectorGrid.setFeatureStyle(id, style);
}
const resetFeatureStyle = (id) => {
vectorGrid.resetFeatureStyle(id);
}
const clearHighlight = (properties) => {
if (highlight.current) {
if (highlight.current !== active.current) {
resetFeatureStyle(highlight.current);
} else {
let st;
if (isFunction(activeStyle)) {
st = activeStyle(properties);
} else if (isObject(activeStyle)) {
st = cloneDeep(activeStyle);
}
if (!isEmpty(st)) {
const base = cloneDeep(baseStyle(properties));
const activeStyle = extend(base, st);
setFeatureStyle(active.current, activeStyle);
}
}
}
highlight.current = null;
}
const clearActive = () => {
if (active.current) {
resetFeatureStyle(active.current);
}
active.current = null;
}
const getFeature = (featureId) => {
const {
data,
idField
} = props;
if (isEmpty(data) || isEmpty(data.features)) return {};
const feature = find(data.features, ({
properties
}) => properties[idField] === featureId);
return cloneDeep(feature);
}
const _propagateEvent = (eventHandler, e) =>{
if (!isFunction(eventHandler)) return;
const featureId = _getFeatureId(e.layer);
const feature = getFeature(featureId);
const event = cloneDeep(e);
const mergedEvent = merge(event.target, {
feature
});
eventHandler(event);
}
let vectorGrid;
if (type === 'slicer') {
vectorGrid = new L.vectorGrid.slicer(data, {
interactive: interactive,
getFeatureId: feature => _getFeatureId(feature),
rendererFactory: L.svg.tile,
vectorTileLayerStyles: vectorTileLayerStyles || {
sliced: (properties, zoom) => {
const bs = baseStyle(properties, zoom);
bs.fill = true;
bs.stroke = true;
return bs;
}
},
...rest
});
} else {
vectorGrid = new L.vectorGrid.protobuf(url, {
interactive: interactive,
key: accessKey,
token: accessToken,
vectorTileLayerStyles: vectorTileLayerStyles,
getFeatureId: feature => _getFeatureId(feature),
rendererFactory: L.canvas.tile,
...rest
});
}
vectorGrid.on('mouseover', (e) => {
const {
properties
} = e.layer;
_propagateEvent(onMouseover, e);
let st;
const featureId = _getFeatureId(e.layer);
if (isFunction(hoverStyle)) {
st = hoverStyle(properties);
} else if (isObject(hoverStyle)) {
st = cloneDeep(hoverStyle);
}
if (!isEmpty(st) && featureId) {
clearHighlight(properties);
highlight.current = featureId;
const base = cloneDeep(baseStyle(properties));
const hoverStyle = extend(base, st);
setFeatureStyle(featureId, hoverStyle);
}
})
.on('mouseout', (e) => {
const {
properties
} = e.layer;
_propagateEvent(onMouseout, e);
clearHighlight(properties);
})
.on('click', (e) => {
const {
properties
} = e.layer;
const featureId = _getFeatureId(e.layer);
_propagateEvent(onClick, e);
let st;
if (isFunction(activeStyle)) {
st = activeStyle(properties);
} else if (isObject(activeStyle)) {
st = cloneDeep(activeStyle);
}
if (!isEmpty(st) && featureId) {
clearActive();
active.current = featureId;
const base = cloneDeep(baseStyle(properties));
const activeStyle = extend(base, st);
setFeatureStyle(featureId, activeStyle);
}
})
.on('dblclick', (e) => {
_propagateEvent(onDblclick, e);
clearActive();
})
.on('contextmenu', (e) => {
_propagateEvent(onContextmenu, e);
clearActive();
});
return {
instance: vectorGrid,
context
}
},
function upgrade(layer, props, prevprops) {
return updateGridLayer(layer, props, prevprops)
}
)
export default VectorGrid;
I am aware this isn't the most elegant solution, but I managed to do this simple react component as a wrapper of leaflet.js, and it works with react-leaflet-v3, so I hope this is helpful for some else out there:
import { useEffect } from "react"; import { useLeafletContext } from "@react-leaflet/core";
import L from "leaflet";
import "leaflet.vectorgrid";
export default function VectorGrid(props) { const { layerContainer, map } = useLeafletContext();
var url = "http://localhost:8082/river_network/{z}/{x}/{y}.pbf";
let options = { rendererFactory: L.canvas.tile, attribution: '© something', };
const vectorGrid = L.vectorGrid.protobuf(url, options);
const container = layerContainer || map;
useEffect(() => { container.addLayer(vectorGrid); return () => { container.removeLayer(vectorGrid); }; }, []);
return null; }
I am aware this isn't the most elegant solution, but I managed to do this simple react component as a wrapper of leaflet.js, and it works with react-leaflet-v3, so I hope this is helpful for some else out there:
import { useEffect } from "react"; import { useLeafletContext } from "@react-leaflet/core";
import L from "leaflet";
import "leaflet.vectorgrid";
export default function VectorGrid(props) { const { layerContainer, map } = useLeafletContext();
var url = "http://localhost:8082/river_network/{z}/{x}/{y}.pbf";
let options = { rendererFactory: L.canvas.tile, attribution: '© something', };
const vectorGrid = L.vectorGrid.protobuf(url, options);
const container = layerContainer || map;
useEffect(() => { container.addLayer(vectorGrid); return () => { container.removeLayer(vectorGrid); }; }, []);
return null; }
You are a lifesaver, thank you! One minor thing, I needed to add this line to my index.html
<script src="https://unpkg.com/leaflet.vectorgrid@latest/dist/Leaflet.VectorGrid.bundled.js"></script>
Do any of you know what else needs to be done for this to work with leaflet 1.8, react-leaflet 4.0 and react 18 ?
Do any of you know what else needs to be done for this to work with leaflet 1.8, react-leaflet 4.0 and react 18 ?
+1
Do any of you know what else needs to be done for this to work with leaflet 1.8, react-leaflet 4.0 and react 18 ?
+1
I created a sample project using create react app that has these working. I hope this helps. https://github.com/flacoman91/react-18-vector-grid-example
The most confusing part for me was understanding the new contexts and the functional component syntax.
You can probably hack around and follow the examples from leaflet vectorgrid here https://github.com/Leaflet/Leaflet.VectorGrid
I created a sample project using create react app that has these working. I hope this helps. https://github.com/flacoman91/react-18-vector-grid-example
The most confusing part for me was understanding the new contexts and the functional component syntax.
You can probably hack around and follow the examples from leaflet vectorgrid here https://github.com/Leaflet/Leaflet.VectorGrid
Thank you so much for this! I have a couple of questions if you don't mind:
- Why do you have react-leaflet-vectorgrid in your package.json if you included your own rewritten version?
- Looking at your VectorGris.js, am I correct to conclude that you have not implemented the entire react-leaflet-vectorgrid wrapper, only the part for loading pre-created tiles from a tile server (protobuf)
- I see in other people's previous comments that they had to do some extra work to make things like popups and tooltips work... does your code support those things? Or no would I need to make those work myself?
@CrazyKidJack You're correct.
You need to include react-leaflet-vectorgrid to get the protobuf part working.
Yes, you have do do a little bit more work to get the other stuff working, but it's really not that hard once you've seen the code working. I can add some more examples so you can see how it works.
@CrazyKidJack You're correct.
You need to include react-leaflet-vectorgrid to get the protobuf part working.
Yes, you have do do a little bit more work to get the other stuff working, but it's really not that hard once you've seen the code working. I can add some more examples so you can see how it works.
Thanks for the speedy reply :) You're right that I can probably figure it out from this. Been look at it about 45minutes and the connections between your version and the original are starting to be come clear.
But more examples always more better if you don't mind providing them :D I'm sure they would help me progress faster
Thanks in advance for your awesomeness
You need to include react-leaflet-vectorgrid to get the protobuf part working.
Is there an easy way for you to explain why? Again, I bet I could figure it out (starting to look at that now)... but if you know and can explain it without it being a burden that would be appreciated.
You need to include react-leaflet-vectorgrid to get the protobuf part working.
Is there an easy way for you to explain why? Again, I bet I could figure it out (starting to look at that now)... but if you know and can explain it without it being a burden that would be appreciated.
I'm not sure. I remember it not working correctly if I tried to remove the dependency and removing
import 'leaflet.vectorgrid';
also causes it to fail.
I think Leaflet has some stuff that are in global scope. I'm not an expert by any means, but I remember spending a good amount of time trying to get things going.
I've updated the example code with the react-leaflet plugins for markers, and circles.
You actually can write your own wrappers around any of the plugins that you see in https://leafletjs.com/plugins.html#markers--renderers
There's way more you can do with interactivity if you add the markers into another component and use some state management like redux to dynamically add/hide/show things. With the vectorgrid, you can tie mouseover/click events into the shapes to do anything you want.
Typically I console.log everywhere to figure out what is going on.
I'm not sure. I remember it not working correctly if I tried to remove the dependency and removing
import 'leaflet.vectorgrid';
also causes it to fail.
Hey so my friend and I looked at it and I think your problem was just that your actual dependency is leaflet.vectorgrid but you didn't include that library directly in your package.json.
The reason that putting react-leaflet-vectorgrid in your package.json fixed it, is because react-leaflet-vectorgrid itself includes leaflet.vectorgrid for you.
So tldr: if you just change your package.json from:
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"leaflet": "^1.9.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-leaflet": "^4.1.0",
"react-leaflet-vectorgrid": "^2.2.1", // CHANGE THIS LINE
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
to
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"leaflet": "^1.9.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-leaflet": "^4.1.0",
"leaflet.vectorgrid": "^1.3.0", // CHANGE THIS LINE
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
without making any other changes, it should work fine :).
@CrazyKidJack awesome!
Thanks for pointing that out. Hooray for open source. I updated the example to demonstrate some of the vectorgrid events.
@CrazyKidJack awesome!
Thanks for pointing that out. Hooray for open source. I updated the example to demonstrate some of the vectorgrid events.
Nono, thank you for continuing to update that example! It's really helping me :)
@flacoman91 Could you help me understand a couple of things in this code block:
I just don't understand what the "style
" and "type
" options are for. I don't understand what they control or where they are consumed. I looked through the Leaflet.VectorGrid documentation and source code as well as the Leaflet documentation and some of the source code and I just don't understand.
I do understand that rendererFactory
, interactive
, and vectorTyleLayerStyles
come from the Leaflet.VectorGrid API/documentation:
I do understand that the "apiKey
" comes form the url template:
But I don't understand what those other two options are for, how they are used, what consumes them, and where the documentation for them is. I thought maybe this was something you added yourself but I didn't see any thing obvious that was using them.
Any help would be appreciated :)
@CrazyKidJack what service are you using to serve up your tiles?
I just copy pasted the example from https://github.com/Leaflet/Leaflet.VectorGrid#dependencies
I think type:protobuf is how the data is read.
If you're using geojson, the type should be slicer
https://github.com/mapbox/vector-tile-spec
The source of your data will determine the protocol that can be used. For work, we use mapbox and vector tiles.
Style is how you want the specific features to look.
the demo here: view-source:https://leaflet.github.io/Leaflet.VectorGrid/demo-vectortiles.html
looks like it's broken, but thats how you can provide a different style for each feature that comes back from the tiles.
Feel free to comment/ open a ticket on the the demo repo I created. I should update it with more advanced examples. I need to find a public demo url/key to mapbox or some other provider. That's a big issue with demonstrating all of these features.