-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to detect viewport changes when viewport is changed programmatically #878
Comments
Store your viewport in state context and use an effect hook to listen to it (jump to the bottom for a note on // ViewportContext.js
import React, {createContext, useState} from 'react';
const ViewportState = createContext();
const ViewportUpdate = createContext();
// Yep! you can use multiple context in one Provider.
// pattern taken from:
// https://kentcdodds.com/blog/how-to-optimize-your-context-value
export function ViewportProvider({children}){
const [viewport, setViewport] = useState();
return (
<ViewportState.Provider value={viewport}>
<ViewportUpdate.Provider value={setViewport}>
{children}
</Viewport
</ViewportState.Provider>
)
}
// expose the state
export function useViewport(){
const context = useContext(ViewportState);
if(context === undefined) throw Error('You forgot to wrap your app in <ViewportProvider />');
return context;
}
// expose the updater
export function useSetViewport(){
const context = useContext(ViewportUpdate);
if(context === undefined) throw Error('You forgot to wrap your app in <ViewportProvider />');
return context;
}
// useViewportData.js - HERE'S WHAT YOU'RE LOOKING FOR
export function useViewportData(){
const viewport = useViewport();
useEffect(() => {
// load new data when viewport changes
}, [viewport])
}
// Example.js - programatic change of viewport. This will only
// render once! Contrived example, however, when you have complex
// UIs you don't want them rendering all the time.
export default function Example(){
const setViewport = useSetViewport();
const onClick = () => setViewport({...});
return <button onClick={onClick}>Move map programmatically</button>
}
// Map.js
export default function Map(){
// we need both the viewport and the updater in this component, though
// that's OK because the map needs to re-render all the time anyway
const viewport = useViewport();
const setViewport = useSetViewport();
// encapsulate loading login in a custom hook.
// this can hypothetically go anywhere - but I've put it here because
// it's coupled with a component that already renders each viewport
// update and it shares concern with the map.
useViewportData();
return <ReactMapGL
{...viewport}
onViewportChange={viewport => setViewport}
/>
}
// App.js - all together now
import React from 'react';
import {ViewportProvider} from './ViewportContext';
import Example from './Example';
import Map from './Map';
export default function App(){
return (
<ViewportProvider>
<Example />
<Map />
</ViewportProvider>
)
} Notes
|
Thank you, this is just what I need. Thank you for very descriptive answer and example. |
I have attached logic to load some features from backend when onViewportChange is called. This works fine when user zoom/pan map.
When I change viewport programmatically by updating the viewport props, the map is moved and zoomed, but onViewportChange is not called.
Is there a way to detect viewport changes when viewport is moved programmatically? Or is there some better way to load features?
I'm having difficulties on loading the features in the same time I update the properties, as the features loading uses the map bounds that I get by
getMap().getBounds()
, but this is updated sometime after the viewport is changed.The text was updated successfully, but these errors were encountered: