Intro to Web Mapping with React.js
Quick and easy guides for building Web Map components in React.js
No beating around the bush — this is a scatter blast series of tutorials showing you how to leverage React.js to build simple Web Map components (think speed dating but with JS Mapping Libraries). We are using some of the more popular Web Mapping Javascript libraries; Mapbox, Leaflet, OpenLayers, ArcGIS and Carto. Nothing fancy here, we are just going to build a simple component for each that renders a map and shows some data. My hope here is to get you hands on with React.js and show you how easy it is to get started. Most importantly I want to get you MAPPING.
Map Component Tutorials
Though I encourage you to follow this introduction in it’s entirety, please feel free to use these links to navigate to each of the individual Mapping Library tutorials (some may still be in the works but I’ll update this article and the sourcecode as I complete each section). You are not required to follow in any particular order nor are you required to complete them all — you can simply just take what you need!
- Part 1— Mapbox
- Part 2— Leaflet
- Part 3—ArcGIS Coming Soon
- Part 4— Carto Coming Soon
- Part 5— OpenLayers Coming Soon
- Mayyybe Part 6 ?— Google Maps let me know in the comments if you want Google Maps added!
1. The Pre-Reqs
I welcome all skill levels willing to embark on their own Web Mapping journey to follow along!
If you haven’t already, you’ll need to install Node.js I recommend installing their latest stable version. You can validate if you have Node installed by typing node -v
in your terminal:
I am using an ancient version of node so don’t follow me off the cliff! 14 has just been my old faithful :)
2. Getting Started with React.js
To get started with react we’ll install the create-react-app
boilerplate globally on our machine — we need this to build our react application
npm install -g create-react-app
This Starter Github Repo has all the code we’ll build in this first part BUT following along may help you understand the design considerations and learn a bit of React.js in the process. We’ll add our Map Components 1 by 1 to this source code in each of the linked tutorials — so if you don’t care about how we built the basic React application simply clone the repo, use npm i
to install all necessary packages and move on the the next part!
NOTE the Tab Functionality in this part is based on this article by Chinedu Imoh.
Our react application is super simple, it allows us to tab through each of the Map Components we’ll code throughout tutorial series — clicking a tab renders a new Map component, but for now it’s just place holder text that loads:
To get started let’s create our react application using our terminal — open VSCode and start a terminal in the directory you want to build your application.
Run create-react-app react-map-tutorial
in the terminal to create our React Application (It may take a few minutes)
We’ll now see a folder containing our application code — let’s cd
into our application cd react-map-tutorial
We can run our application using npm start
and by default a browser should open but if not simply navigate to the Local:
url output in the terminal to view your application:
Navigating to the Localhost url — we should see something similar to this in our browser, this is our React app in it’s current state:
All the code we’ll care about for this will live in the react-map-tutorial/src
directory. Let’s discuss a few of the files in our application:
index.js
is just like an index.html file if we run our app it always points to it’s index file unless we configure it not to. We aren’t going to do anything with the index file for this tutorial but, if we look at it, we can see it is responsible for rendering our main component (app.js).app.js
is our main application component — it’s basically a container that will hold all our components and where/how we render them.app.css
this is our main components styling file it can also be used as the parent styling file for components we’ll render in our app.js.
3. Getting hands on with our React App
Replace all the code in our app.css
with this:
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
/* main component styling */
.App {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
/* Tab component css*/
.Tabs{
width: 80%;
height: auto;
min-height: 80%;
background: #ffffff;
border: 1px solid #6bb7d8;
margin: 3.5rem auto 1.5rem;
padding: 2rem 1rem;
color: #003a53;
border-radius: 2rem;
@media (max-width: 769px) {
padding: 2rem 0;
}
}
/* Tab Navigation */
ul.nav {
width: 60%;
margin: 0 auto 2rem;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid #6bb7d8;
border-radius: 2rem;
padding-left: 0px;
@media (max-width: 768px) {
width: 90%;
}
}
ul.nav li {
width: 50%;
padding: 1rem;
list-style: none;
text-align: center;
cursor: pointer;
transition: all 0.7s;
}
ul.nav li:first-child {
border-bottom-left-radius: 2rem;
border-top-left-radius: 2rem;
}
ul.nav li:last-child {
border-bottom-right-radius: 2rem;
border-top-right-radius: 2rem;
}
ul.nav li:hover {
background: #6bb7d8;
}
ul.nav li.active {
background: #6bb7d8;
}
/* Tab Content Styles */
.TabContent {
font-size: 2rem;
text-align: center;
}
Replace all the code in ourapp.js
with this
import "./App.css";
const App = ()=> {
return (
<div className="App">
</div>
);
}
export default App;
Our main component is a function calledApp
that returns html content that will contain our Map Components. We export this App
function so we can import it in index.js
and our application knows how to render it — MAGIC!
Create a folder in react-map-tutorial/src
called “Components” in that new directory make 2 sub directories called “MapComponents”, “TabComponent”
In our now react-map-tutorial/src/TabComponent
we are going to write code that renders our tabs and adds functionality they need to render a component. create a file called Tabs.js
— this is our component that will display our tab “buttons” — in Tabs.js add the following
import React, { useState } from "react";
const Tabs = () => {
const [activeTab, setActiveTab] = useState("map1");
return (
<div className="Tabs">
<ul className="nav">
<li className={activeTab === "map1" ? "active" : ""}>Map 1</li>
<li className={activeTab === "map2" ? "active" : ""}>Map 2</li>
</ul>
<div className="outlet">
{/* Map Components will go here */}
</div>
</div>
);
};
export default Tabs;
Okay so we have our Tabs component function that is returning our Tabs html with the Tab Links under the <ul>
tag and then where we intend to render our Map Components under our outlet <div>
tag
You’ll notice we have some fancy expressions {activeTab === "map1" ? "active" : ""}
in our Tab LinksclassName
<li className={activeTab === "map1" ? "active" : ""}>Map 1</li>
<li className={activeTab === "map2" ? "active" : ""}>Map 2</li>
We are using the react lifestyle hook called useState where we add activeTab
and setActiveTab
properties to our Tab component.
You can see that I just tell our component that I want to set this state on “map1”
by default which will make the condition true and set the className
to be “active”
for “map 1”
(REMEMBER in our app.css
we have a style rule for this active class which will highlight the link ul.nav li.active
) — In just a moment we’ll add functionality that will set the state on the Tab Links per user interaction.
You can see we are exporting out with export default Tabs;
we’ll import this component to our App.js
component to display it in our application
Go ahead and update our App.js
to have our Tabs
component imported and add our imported component in the code that is returned — You see how easy this is? Now the Tab component we made just fits right into our Main App component - it’s magic!
import "./App.css";
import Tabs from "./Components/TabComponent/Tabs";
const App = () => {
return (
<div className="App">
<Tabs />
</div>
);
}
export default App;
Our application will now look like this — note the Map 1 Tab highlighted
Create 2 new JavaScript files in react-map-tutorial/src/TabComponent
TabNavItem.js
this component will be used to represent a Tab Link navigation item — we’ll dynamically set the active className
using the activeTab
property and then set a new active tab with the setActiveTab
property
/*
NOTE the Tab Functionality in this part is taken from this article
by Chinedu Imoh https://blog.logrocket.com/how-to-build-tab-component-react/
*/
import React from "react";
const TabNavItem = ({ id, title, activeTab, setActiveTab }) => {
const handleClick = () => {
setActiveTab(id);
};
return (
<li onClick={handleClick} className={activeTab === id ? "active" : ""}>
{ title }
</li>
);
};
export default TabNavItem;
TabContent.js
this component is used to dynamically render the Map Component content inside our Tabs component using the id
and activeTab
property — the { children }
syntax renders ensures all the child components are referenced
/*
NOTE the Tab Functionality in this part is taken from this article
by Chinedu Imoh https://blog.logrocket.com/how-to-build-tab-component-react/
*/
import React from "react";
const TabContent = ({id, activeTab, children}) => {
return (
activeTab === id ? <div className="TabContent">
{ children }
</div>
: null
);
};
export default TabContent;
Now lets go back to Tabs.js
and do a big overhaul — we are going to import our new TabComponent
and TabNavItem
components. Using this new functionality we'll add a TabNavItem
component (to navigate) and a TabContent
Component (with some place holder text) for each Map Component we plan on building in the rest of this tutorial series:
import React, { useState } from "react";
import TabNavItem from "./TabNavItem.js";
import TabContent from "./TabContent.js";
const Tabs = () => {
const [activeTab, setActiveTab] = useState("mapbox");
return (
<div className="Tabs">
<ul className="nav">
<TabNavItem title="Mapbox" id="mapbox" activeTab={activeTab} setActiveTab={setActiveTab}/>
<TabNavItem title="Leaflet" id="leaflet" activeTab={activeTab} setActiveTab={setActiveTab}/>
<TabNavItem title="OpenLayers" id="openlayers" activeTab={activeTab} setActiveTab={setActiveTab}/>
<TabNavItem title="ArcGIS" id="arcgis" activeTab={activeTab} setActiveTab={setActiveTab}/>
<TabNavItem title="Carto" id="carto" activeTab={activeTab} setActiveTab={setActiveTab}/>
</ul>
<div className="outlet">
<TabContent id="mapbox" activeTab={activeTab}>
<p>Mapbox works!</p>
</TabContent>
<TabContent id="leaflet" activeTab={activeTab}>
<p>Leaflet works!</p>
</TabContent>
<TabContent id="openlayers" activeTab={activeTab}>
<p>OpenLayers works!</p>
</TabContent>
<TabContent id="arcgis" activeTab={activeTab}>
<p>ArcGIS works!</p>
</TabContent>
<TabContent id="carto" activeTab={activeTab}>
<p>Carto works!</p>
</TabContent>
</div>
</div>
);
};
export default Tabs;
Our application should now look like this:
Clicking each individual TabNavItem
should change the rendered TabContent
Text
4. To Conclude
I know we didn’t create any maps in this intro but I trust you see how easy it is to get started with React.js— there’s a reason it has become the go to Frontend JavaScript Framework for Developers and I hope you consider it as your FE JavaScript Framework for your next Web Mapping project.
I hope you found this tutorial helpful at getting hands on with React.js and I trust you’ll find individual tutorials for each JavaScript mapping Library Useful too. Choosing a JavaScript Web Mapping library can be difficult and depends on numerous different factors — at the surface these libraries all basically do the same thing but as you peel back the layers of each you find they each have their own strengths and weaknesses. It’s a good idea to research them thoroughly and find the one that works for you and your business needs. If you need some help deciding on a JS Web Mapping libraries to use, feel free to reach out and I’ll be happy to offer assistance where ever possible.
5. The Sourcecode
What kind of monster would I be if I didn’t include the source code? Here are 2 Github Repo’s:
- Starter Repo for you to follow each Map tutorial with https://github.com/GISJohnECS/react-map-tutorial
- Repo containing the complete codebase for each part in this Tutorial series https://github.com/GISJohnECS/react-map-full (NOTE I’ll be completing each tutorial one by one so the Repo will be updated as I finish each tutorial)
Credit where it’s due:
Special thank you to Chinedu Imoh for his work on his How to build a tab component in React article which served as the foundation for this tutorial.