Using React-Leaflet with a React/ Redux Application
Published: 2021-06-25 20:56:39

When I first started my ReactJS project, BrewDog, I heard the horror stories of writing poor code when using Google Maps Javascript API, and wanted a free resource for rendering maps. I wanted to be sure I would not get a random bill for thousands of dollars from Google, so if you're trying to create a React app and want to have a completely free mapping service, look no further than React-Leaflet! It's an easy way to display a map in a React Component and render it with whatever information you want to use from your application's state. This post will give you step by step instruction on implementing React-Leaflet. These instructions assume you are comfortable with Javascript, React, and Redux concepts and also assumes you have set up your application through 
```
create-react-app (your project name here)
```
 So first things first let's set up our project to be able to create a map.

## Step 1. Install Required NPM Packages

First thing you need to do is run the following command in your terminal to ensure your have the required node packages installed. 
```
npm install react react-dom leaflet react-leaflet
```
## Step 2. Add Script Tag and CSS Link to index.html

Add the stylesheet link in the header of your index.html file FIRST!!!!!
```
 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
   integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
   crossorigin=""/>
```
Next add this script tag below where the stylesheet link was added (still in the header of your index.html).
```
 <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
   integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
   crossorigin=""></script>
```

## Step 3. Revise Package.json

You will need to do this so that Leaflet is compatible with your browser, when working with Chrome. Go into package.json and make the following changes.

#### Before
```
 "browserslist": {
   "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
},
```

#### After
```
"browserslist": [
   ">0.2%",
  "not dead",
  "not op_mini all"
],
```
## Step 4. Create Map.js file and Import Necessary Components

Create a new file in your src/components folder called Map.js and put the following lines at the top.
```
import React from 'react';
import { connect, useSelector } from 'react-redux';
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet'
```
## Step 5. Create a Map Component to Hold Leaflet Map

Below is an example of how I created a component in one of my applications. YOU NEED TO SPECIFY THE HEIGHT IN PIXELS OR IT WILL NOT RENDER ON THE SCREEN!!! Personally I find it much easier to style this map inline but you can do it in an external stylesheet if you prefer!
```

Const Map = () => {
return (
              <div id="mapid">
             <MapContainer center={[39.809860, -96.555183]} zoom={4} scrollWheelZoom={false} style={{
                      height:"650px",
                      width: "900px"
                  }}>
                <TileLayer
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
            
            </MapContainer>
            </div>
                   )};
```

## Step 6. Handling Centering and Zooming Upon Changes in State
So a really tricky aspect of using Leaflet is making your map rerender properly upon changes in state. If your map is zoomed into one location upon the first render, the map will not adjust if you want it to rerender on a different location. So create this functional component here to pass to your MapContainer. This functional component needs to be declared OUTSIDE of your map component.
```
function ChangeView({ center, zoom }) {
  const map = useMap();
  map.setView(center, zoom = 12);
  return null;
}
```
Below your MapContainer opening statement, and above the Tile Layer component call this functional component with the new center or zoom attributes you would like your map to refocus on. 
For Example:  
```
 <MapContainer center={[searchedBreweries[0].latitude, searchedBreweries[0].longitude]} zoom={12} scrollWheelZoom={false} style={{
                            height:"700px",
                            width: "900px"
                        }}>
                        <ChangeView center={[searchedBreweries[0].latitude, searchedBreweries[0].longitude]} />
    <TileLayer
      attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    />
```

## You're Done!

After following those steps you should be all set and ready with your map, and having it rerender as needed. You will have to put conditional clauses on how this component returns if it is relying on your state to do things such as place markers on the map. Multiple if else statements above your return clause such as the example below allow you to do this. 
```
if(* state exists *){
    return(
      <div id = "mapid">
    <MapContainer />
</div>
```

But other then that this guide should have you with a fully functional and FREE Leaflet map.