Skip to content
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

Nextjs13 and react leaflet: Dynamic loaded Marker in FeatureGroup unable to call getBounds #1090

Open
7 tasks done
a-marcel opened this issue Aug 26, 2023 · 0 comments
Open
7 tasks done

Comments

@a-marcel
Copy link

Bug report in v4

  • All peer dependencies are installed: React, ReactDOM and Leaflet.
  • Using the latest version of React and ReactDOM v18.
  • Using the supported version of Leaflet (v1.8.0 minimum) and its corresponding CSS file is loaded.
  • Using the latest v4 version of React-Leaflet.
  • The issue has not already been reported.
  • Make sure you have followed the quick start guide for Leaflet.
  • Make sure you have fully read the documentation and that you understand the limitations.

I currently play around with the new nextjs13 and the app directory as well as server side only code. In my project i use React leaflet and this cannot be directly used anymore in Nextjs13 (with the app directory). It is required to load the client components differently or via dynamic. In my project i use the 2nd option via dynamic and created a File for the components that can be lazy loaded:

  const ClientSideMap = dynamic(() => import('@components/Map'), { ssr: false })
    
    type Props = {
        center?: number[];
        locationValue?: string;
        children?: ReactNode;
    };
      
    const ClientMap = forwardRef((props : Props, mapRef) => (
        <ClientSideMap {...props} forwardedRef={mapRef} />
    ))
    ClientMap.displayName = 'ClientMap';
    
    export default ClientMap;

    const ClientSideMarker = dynamic(() => import('@components/Marker'), { ssr: false })
    
    type MarkerProps = {
        center?: number[];
        locationValue: L.LatLngExpression;
        children?: ReactNode;
        id: string | number;
    };
      
    
    export const Marker = forwardRef(({ center, locationValue, children, id }: MarkerProps, markerRef) => {
        return (
            <ClientSideMarker locationValue={locationValue} id={id} ref={markerRef}>
                <Popup>
                    {children}
                </Popup>
            </ClientSideMarker>
        )
    })
    Marker.displayName = 'Marker'

These dynamic components are loaded in the app/page.tsxfile

import Map, { Marker } from '@components/MapLazyComponents'

export const dynamic = "force-dynamic";

export default async function Home() {
    const result = await getData() || {};

    // console.log("Data", result)

    return (
        <main>
            <div style={{
                width: '400px',
                height: '400px'
            }}>
                <Map>
                    {result.map(m => (
                        <Marker key={m.id} locationValue={[m.lat as number, m.lng as number]} id={m.id}>{m.id} - {m.name}</Marker>
                    ))}
                </Map>
            </div>
        </main>
    );
}

When I run this project, it works like expected and i can see a map with the configured markers.

Actual behavior

I would like to set the Zoom the map in that way, that all Markers are visible. Leaflet offer a possibility for that use-case by using getBounds.

useEffect(() => {
    console.log("Map test", featureGroupRef.current, featureGroupRef.current?.getLayers())
    if (map && featureGroupRef.current) {
      console.log("Bounds", featureGroupRef.current)
      // map.fitBounds(featureGroupRef.current.getBounds());
    }
  }, [map, featureGroupRef]);

Unfortunately, this is not working (Error: Error: Bounds are not valid. - Thrown in that Line). After some debugging i assume that this is reladed to the dynamic loading of Markers. In the code lines above, you can see that i log some lines after the Map is loaded. The Layers the Map is empty but in the console.log it's possible to see that there is an array with layers that contains the Marker.

Thanks a lot

P.s.: I know that I can change the way and pass the marker data via Json down to the MapComponent without a use of dynamic. But I really would like to use it in the way where everything is prepared in the page.tsxfile - so on the server side.

Expected behavior

The map should set the boundaries where all marker fit.

Steps to reproduce

Since this is a more complex problem, I created a github repo where the issue is visible. https://github.com/a-marcel/nextjs13-app-dynamic-loaded-marker/tree/main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant