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.

Image

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.

Copy
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.

Copy
yarn add @appbaseio/reactivemaps @appbaseio/reactivesearch

or

Copy
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

Copy
<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.

Copy
	<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

Copy
<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.

create an appbase.io app

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.

Dataset

We will update our src/App.js file to add ReactiveBase component.

Copy
// ... 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.

Copy
	<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.

Copy
<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" />
        &nbsp;{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:

Copy
renderItem={(result) => ({
  custom: (
    <div
      style={{
        background: "dodgerblue",
        color: "#fff",
        paddingLeft: 5,
        paddingRight: 5,
        borderRadius: 3,
        padding: 10
      }}
    >
      <i className="fas fa-globe-europe" />
      &nbsp;{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.

Copy
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" />
                    &nbsp;{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.

Copy
<script src="https://cdn.jsdelivr.net/npm/@appbaseio/[email protected]/umd/reactivemaps.js"></script>

A GZip version is also available at https://cdn.jsdelivr.net/npm/@appbaseio/[email protected]/umd/reactivemaps.js.gzip.