Error encountered when attempting to assign a Leaflet Icon to a specialized Type within NextJs

While working on my React Leaflet map, I encountered an error when trying to incorporate various Icons:

Error: ReferenceError: window is not defined

The issue arises only when adding a specific Leaflet Icon in my custom type. The map renders flawlessly without the Icon, but I desire to have multiple dynamic Icons displayed. Here's a snippet from my Map.tsx file:


    // Import statements and component definition...
  

I utilize this component in a section where users can choose which icon to place on the map:


    // Another component importing forestTypes data...
  

The ForestTypes data structure is defined as follows:


    // Definitions of green, pink icon instances and forestTypes array...
  

Additionally, in leaflet.d.ts file, I specify the ForestTypes interface:


    // Declaration of ForestTypes interface...
  

Despite dynamically importing the Leaflet map and disabling SSR, I still encounter the same error regarding using Icons. Any insights or solutions for rendering the map with diverse Icons would be greatly appreciated.

If you've faced a similar challenge or can offer guidance on resolving this issue, please share your thoughts!

Answer №1

Are your SVGs accessible on the URLs provided? Upon inspecting the leaflet marker typings, I observed that the Icon also features an imagePath which could be utilized.

Personally, I have achieved excellent outcomes by utilizing DivIcon for custom markers. DivIcons support static HTML content, allowing you to incorporate any HTML elements and even ReactElements with appropriate coding.

import { divIcon } from "leaflet";
import { ReactElement } from "react";
import { renderToString } from "react-dom/server";

export const createLeafletIcon = (
  icon: ReactElement,
  size: number,
  className?: string,
  width: number = size,
  height: number = size,
  center: boolean = false
) => {
  const widthAnchor = width / 2;
  const heightAnchor = center ? height / 2 : height;
  return divIcon({
    html: renderToString(icon),
    iconSize: [width, height],
    iconAnchor: [widthAnchor, heightAnchor],
    popupAnchor: [0, -heightAnchor],
    className: className ? className : "",
  });
};

In your specific context, simply prepare the icons as reusable React components across different sections of your application.

Below is a customized marker component for contextual reference:

import { LatLngLiteral } from "leaflet";
import React, { Children, ReactElement, useEffect, useRef } from "react";
import { Marker, Popup, useMap } from "react-leaflet";
import { MapPin } from "tabler-icons-react";
import { createLeafletIcon } from "./utils";

// The component remains unchanged beyond this point</answer1>
<exanswer1><div class="answer accepted" i="75482444" 4.0" c="1676615611" a="RGlzY28=" ai="11196441">
<p>Are your svgs accessible on the urls you provide? When I look into the leaflet marker typings I noticed that <code>Icon also have a imagePath that you could try to use instead.

However I have great success with using DivIcon for custom markers. DivIcons can handled static html, which means that you can use any html you want and with some code you can use ReactElements.

import { divIcon } from "leaflet";
import { ReactElement } from "react";
import { renderToString } from "react-dom/server";

export const createLeafletIcon = (
  icon: ReactElement,
  size: number,
  className?: string,
  width: number = size,
  height: number = size,
  center: boolean = false
) => {
  const widthAnchor = width / 2;
  const heightAnchor = center ? height / 2 : height;
  return divIcon({
    html: renderToString(icon),
    iconSize: [width, height],
    iconAnchor: [widthAnchor, heightAnchor],
    popupAnchor: [0, -heightAnchor],
    className: className ? className : "",
  });
};

In your case just prepare the icons as react components that you can reuse in other instances in your application as well.

This is my custom marker component for some context

import { LatLngLiteral } from "leaflet";
import React, { Children, ReactElement, useEffect, useRef } from "react";
import { Marker, Popup, useMap } from "react-leaflet";
import { MapPin } from "tabler-icons-react";
import { createLeafletIcon } from "./utils";

export interface LeafletMarkerProps {
  position: LatLngLiteral;
  flyToPosition?: boolean;
  size?: number;
  color?: string;
  icon?: ReactElement;
  defaultOpen?: boolean;
  onOpen?: () => void;
  children?: React.ReactNode;
  markerType?: string;
  zIndexOffset?: number;
  centerMarker?: boolean;
}

const LeafletMarker: React.FC<LeafletMarkerProps> = ({
  position,
  flyToPosition = false,
  children,
  size = 30,
  color,
  defaultOpen = false,
  onOpen,
  icon = <MapPin size={size} color={color} />,
  markerType,
  zIndexOffset,
  centerMarker = false,
}) => {
  const map = useMap();

  const markerRef = useRef(null);
  position && flyToPosition && map.flyTo(position);

  const markerIcon = createLeafletIcon(
    icon,
    size,
    markerType,
    size,
    size,
    centerMarker
  ); // Important to not get default styling
  useEffect(() => {
    if (defaultOpen) {
      try {
        if (markerRef.current !== null && !markerRef.current.isPopupOpen()) {
          markerRef.current.openPopup();
        }
      } catch (error) {}
    }
  }, [defaultOpen, position.lat, position.lng]);

  return (
    <Marker
      eventHandlers={{
        popupopen: () => onOpen && onOpen(),
      }}
      ref={markerRef}
      icon={markerIcon}
      position={position}
      zIndexOffset={zIndexOffset}
    >
      {/* autoPan important to not have jittering */}
      {children && <Popup autoPan={false}>{children}</Popup>}
    </Marker>
  );
};

export default LeafletMarker;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling with implementing click events on Ionic-Calendar 2?

Attempting to implement a (click) event for ionic-calendar 2 where it deactivates a button if the user clicks on a date that has already passed. The issue I am facing is that when I initially click on a past date, the button remains enabled. However, upon ...

Encountering a compilation error when implementing ActionReducerMap in combination with StoreModule.forFeature

In my Angular project, the structure is organized as follows: /(root or repo folder) |_ projects |_ mylib (main library to be exported from the repo) |_ sample-app (created for testing 'mylib' project in other projects) To manage appli ...

Tracking user session duration on a React Native app can be achieved by implementing a feature that monitors and

I'm currently focusing on tracking the amount of time a user spends on the app in minutes and hours, and displaying this information. I have successfully implemented the functionality to count minutes, but I am struggling to figure out how to track wh ...

Loading data synchronously in Angular6 routes

After recently integrating Server-Side Rendering (SSR) into my Angular6 application to render dynamic HTML in a crawlable manner, everything appears to be functioning properly. But I am facing an issue when trying to render data from an API endpoint. Upon ...

Refresh a doughnut chart in real-time using NG2Charts

Currently, I am in the process of developing a macronutrient calculator as part of a project. The idea is to have a form where users can input values, and a corresponding doughnut chart will display with initial values set at 0. However, upon clicking the ...

Could there be an issue with the way I've implemented my setInterval function?

I am currently in the process of developing a stopwatch feature using React Native and implementing the setInterval function to increase a counter and update the state accordingly: Play Function (triggered upon pressing the play button) const [isRunning ...

When utilizing the Turf.nearPoint() function, it is important to consider the type of point being used. The documentation for Turf.nearestPoint() appears to be inaccurate

I have some code that needs to be transcribed from another system, so unfortunately I can't easily share it here. If I could, I would just post the entire project. Recently, I attempted to integrate into our project but encountered error messages. T ...

When trying to incorporate aws-sdk into Angular2, an error message stating "Module 'stream' cannot be found" may occur

I encountered the following issues: Error TS2304: Cannot find name 'Buffer', https://github.com/aws/aws-sdk-js/issues/994 and Using aws-sdk with angular2 Even though my typings and @types/node seem to be properly installed, I am still encount ...

Waiting for the completion of the previous observable in an RxJS Interval Observable

I'm trying to create an interval observable that waits for the last execution before proceeding. Here are some attempts I've made: First attempt: interval(1000) .subscribe(async x => { await new Promise(resolve => setTimeout(resolve, ...

Angular error: Attempting to reduce an empty array without an initial value

I am encountering an issue with my array being filtered and reduced. getPageComponents(title: string) { this.pageComponents = []; const pageBlock = this.pageComponents.filter((val) => { if (val.page_title === title) { retur ...

Conceal the HTML element within a subscription

Currently, I am utilizing Angular and have a checkbox that I need to toggle visibility based on the response of an API call subscription. The issue lies in a delay when trying to hide the checkbox (as it is initially set to visible). My assumption is that ...

Utilizing i18next with nextJs integration

I have a Next.js application where I am utilizing next-translate for internationalization. The frontend part is working great with this setup. However, I also have an API built with Next.js (pages/api) and I would like to implement internationalization the ...

TS6059 found in excluded folder

I'm facing an issue with my tsconfig.json file that looks like this: {"compilerOptions": { "module": "commonjs", ...

Uncovering the websocket URL with NestJS and conducting postman tests: A step-by-step guide

Creating a mean stack application using NestJS involves utilizing websockets. However, testing websockets in Postman can be confusing. Typically, I test route URLs in Postman and get output like: "http://localhost:3000/{routeUrl}". But when it comes to tes ...

Error in Next.js using next-auth/react: "PrismaClient cannot be executed in the browser"

Currently, I am in the process of developing a Next.js application and implementing authentication using the next-auth/react package. One of the server-side functions I have created utilizes PrismaClient to retrieve information about the current user based ...

Suggestions on coloring polyline segments according to the density of neighboring segments surrounding the specific polyline segment

Apologies for the lengthy title, but I am interested in developing a polyline heatmap that changes color based on the number of lines within a certain proximity. Here is an example of what I have in mind: https://i.sstatic.net/W2lox.jpg Are there any inn ...

Having trouble moving NEAR tokens between accounts with near-api-js

I am attempting to move NEAR tokens between two testnet wallets using the near-api-js library in NextJS When I run the send money function of the account, I encounter the following error import { connect, keyStores } from "near-api-js"; export ...

Is it possible to minimize the number of accessors needed for reactive forms?

Currently, I am dealing with a reactive form that consists of 20 different inputs. An example of one input is shown below: <input formControlName="name" matInput> For each input, I find myself needing to write an accessor function like the ...

Tips for setting up a mailing server using Next.js

As a newcomer to Next.js, I'm looking to add a mailing feature to a contact form on my site. Given that Next.js is SSR, I'm curious if I still need a separate backend environment to install a mailer like Node.js and Nodemailer, or if the mailer c ...

What's the best way to modify the React state following a successful tRPCv10 request?

Looking to adapt the new tRPC version 10 for a basic shopping list CRUD Nextjs app. Managed to set up the tRPC endpoint successfully with "get all" and "create" handlers, both working fine when tested from the front end. However, facing an issue updating t ...