ReactiveMaps is a complimentary library to ReactiveSearch. Map components require ReactiveSearch architecture and its root component to begin with. If you wish to build anything on reactivemaps, you'll need to install reactivesearch along with it.
Existing users can checkout the migration guide to switch to the newest version of ReactiveMaps library.
Step 0: Create Boilerplate
In this section, we will create a search UI based on an earthquake dataset with ReactiveSearch components.
Caption: Final image of how the app will look.
We can either add ReactiveSearch to an existing app or create a boilerplate app with Create React App (CRA). For this quickstart guide, we will use the CRA.
create-react-app my-awesome-search && cd my-awesome-search
Step 1: Install ReactiveMaps and ReactiveSearch
We will fetch the reactivemaps
and reactivesearch
modules using yarn or npm.
yarn add @appbaseio/reactivemaps @appbaseio/reactivesearch
or
npm install --save @appbaseio/reactivemaps @appbaseio/reactivesearch
Selecting Map Library
ReactiveMaps supports OpenStreet Map and Google Map libraries for rendering map. Depending on the Map library you choose, Following are the dependencies that you will have to add.
OpenStreet Maps
<ReactiveOpenStreetMap />
uses React-Leaflet for rendering Openstreet maps. For rendering maps correctly, add the following stylesheet
in the <head>
element of public/index.html
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" rel="stylesheet" />
Google Maps
<ReactiveGoogleMap />
uses Google Maps JS library to render the google map and access the necessary geo-location services. Pass the secret google key to the ReactiveBase
wrapper component using mapKey
prop and that's it.
<ReactiveBase
// ...
mapKey="<YOUR_MAP_KEY>"
>
</ReactiveBase>
Additionally, pass the mapLibraries
prop to load additional google libraries like places
, visualization
, etc.
The following are available according to Google Docs:
- drawing
- geometry
- localContext
- places
- visualization
<ReactiveBase
mapKey="<YOUR_MAP_KEY>"
mapLibraries={['visualization', 'places']}
// ...other props
/>
Mandatorily pass
mapLibraries={['places']}
when using either or both of GeoDistanceDropdown/ GeoDistanceSlider components from ReactiveMaps 🗺️ .
Step 2: Adding first component
Lets add our first ReactiveSearch component: ReactiveBase, it is a backend connector where we can configure the Elasticsearch index / authorization setup.
We will demonstrate creating an index using appbase.io service, although you can use any Elasticsearch backend within ReactiveBase.
Caption: For the example that we will build, the app is called earthquakes and the associated read-only credentials are a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61. You can browse and clone the dataset into your own app from here.
We will update our src/App.js
file to add ReactiveBase component.
// ... other imports
import { ReactiveBase } from '@appbaseio/reactivesearch';
class App extends Component {
render() {
return (
<ReactiveBase
app="earthquakes"
url="https://a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61@appbase-demo-ansible-abxiydt-arc.searchbase.io"
enableAppbase
mapKey="AIzaSyA9JzjtHeXg_C_hh_GdTBdLxREWdj3nsOU"
>
{/* // other components will go here. */}
<div>Hello ReactiveSearch!</div>
</ReactiveBase>
);
}
}
This is how the app should look after running the yarn start
command.
Step 3: Adding Filters and Map Component
For this app, we will be using SingleList component for filtering the dataset. And ReactiveGoogleMap component for showing the search results. Lets add them within the ReactiveBase component. But before we do that, we will look at the important props for each.
<SingleList
title="Places"
componentId="places"
dataField="place.keyword"
size={50}
showSearch
/>
SingleList creates a radio-buttons list UI component that is connected to the database field passed as dataField
prop to the SingleList component.
Next, we will look at the ReactiveGoogleMap component for creating a map component.
<ReactiveGoogleMap
style={{ height: "90vh" }}
componentId="googleMap"
dataField="location"
defaultMapStyle="Light Monochrome"
title="Reactive Maps"
defaultZoom={3}
size={50}
react={{
and: "places"
}}
onPopoverClick={(item) => <div>{item.place}</div>}
showMapStyles={true}
renderItem={(result) => ({
custom: (
<div
style={{
background: "dodgerblue",
color: "#fff",
paddingLeft: 5,
paddingRight: 5,
borderRadius: 3,
padding: 10
}}
>
<i className="fas fa-globe-europe" />
{result.magnitude}
</div>
)
})}
/>
The react
prop here specifies that it should construct a query based on the current selected value of the singlelist(places) component. Every time the user changes the selected value, a new query is fired -- you don't need to write a manual query for any of the UI components here, although you can override it via customQuery
prop.
This is how the map component's UI would look like. Notice how it is rendering the magnitude values of the earthquake in place of the marker pins. We achieved this via renderItem
prop in the ReactiveGoogleMap component:
renderItem={(result) => ({
custom: (
<div
style={{
background: "dodgerblue",
color: "#fff",
paddingLeft: 5,
paddingRight: 5,
borderRadius: 3,
padding: 10
}}
>
<i className="fas fa-globe-europe" />
{result.magnitude}
</div>
)
})}
You can also customise it to render any kind of marker pins. Refer ReactiveGoogleMap's documentation for the same.
Now, we will put all three components together to create the UI view.
import ReactDOM from "react-dom/client";
import { Component } from "react";
import { ReactiveBase, SingleList } from "@appbaseio/reactivesearch";
import { ReactiveGoogleMap } from "@appbaseio/reactivemaps";
class App extends Component {
render() {
return (
<ReactiveBase
app="earthquakes"
url="https://a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61@appbase-demo-ansible-abxiydt-arc.searchbase.io"
enableAppbase
mapKey="AIzaSyA9JzjtHeXg_C_hh_GdTBdLxREWdj3nsOU"
>
<div>
<SingleList
title="Places"
componentId="places"
dataField="place.keyword"
size={50}
showSearch
/>
<hr />
<div style={{ padding: "2rem" }}>
<ReactiveGoogleMap
style={{ height: "90vh" }}
componentId="googleMap"
dataField="location"
defaultMapStyle="Light Monochrome"
title="Reactive Maps"
defaultZoom={3}
size={50}
react={{
and: "places"
}}
onPopoverClick={(item) => <div>{item.place}</div>}
showMapStyles={true}
renderItem={(result) => ({
custom: (
<div
style={{
background: "dodgerblue",
color: "#fff",
paddingLeft: 5,
paddingRight: 5,
borderRadius: 3,
padding: 10
}}
>
<i className="fas fa-globe-europe" />
{result.magnitude}
</div>
)
})}
/>
</div>
</div>
</ReactiveBase>
);
}
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
If you have followed along, this is how our app should look now.
For convenience, you can checkout the final code from the CodeSandbox above.
Step 4: ReactiveMaps as UMD
It is also possible to run ReactiveMaps without relying on a Node.JS environment tooling for the build setup.
<script src="https://cdn.jsdelivr.net/npm/@appbaseio/reactivemaps@4.0.0-alpha.1/umd/reactivemaps.js"></script>
A GZip version is also available at https://cdn.jsdelivr.net/npm/@appbaseio/reactivemaps@4.0.0-alpha.1/umd/reactivemaps.js.gzip.