How to Build an Airbnb clone with React and ElasticSearch

Written by anuj-shah | Published 2019/09/11
Tech Story Tags: reactjs | appbaseio | reactivesearch | react | javascript | airbnb-clone | software-development | elastic-search

TLDR This blog post will help you build powerful search UI experiences similar to Airbnb's. I will do this using ReactiveSearch - the most popular React UI components library for building search interfaces. In the process, you will also learn about about how to work with ElasticSearch with React. We will be using the open-source search engine ElasticSearch and ReactiveMaps to build the Airbeds app in this post. We'll go step by step to build our application and use these tools to help you write code.via the TL;DR App

This blog post will help you build powerful search UI experiences similar to Airbnb's. I will do this using ReactiveSearch - the most popular React UI components library for building search interfaces. I will do this by breaking down the UI into components so this will be helpful to build any search UI. In the process, you will also learn about about how to work with ElasticSearch.
ReactiveSearch v3 is just out now. You can read all about it here. If you have already worked with an earlier version ReactiveSearch, this post will also guide you wrt the breaking changes for v3 and how you can upgrade your components.
You should try out the Live Demo of our final app here to see what we will be building. I will wait for you!
What is ElasticSearch and why should you care about it?
Now, let’s understand the role of ElasticSearch in helping us build the above UI. ElasticSearch is a super-fast, open-source, full-text search engine. It allows you to store, search, and analyse big volumes of data quickly (we are talking milliseconds here). It is generally used as the underlying engine/technology that powers applications that have complex search features and requirements. You can read more about it here.
With ElasticSearch, you can build a fast search utilising its powerful Query DSL. However, setting up ElasticSearch correctly requires a lot of work. For instance, the data mapping, analysers and tokenisers need to be set correctly or you may not receive accurate search results back. Besides, the more filters that get applied along with the search query, the more complex the resulting search query becomes.
We, at Appbase, have built some open-source tools to help you do all these things with the matter of some clicks.
  • A tool to add data into ElasticSearch — Importer
  • A tool to view ElasticSearch data like an excel sheet — Data Browser
  • A tool to generate relevant ElasticSearch queries easily — Query Builder
In this blog post, with the help of some of these tooling, we will utilise the strengths of ElasticSearch with React to build powerful apps.
How to use ElasticSearch with React?
We will be using ReactiveSearch and ReactiveMaps open-source libraries to build the Airbeds app in this post. These libraries offer a range of highly customisable rich UI components that can connect with any ElasticSearch server and provide you with an appropriate default search query for all generic use-cases (like E-commerce, Yelp, Meetups, etc) bundled into these components. ReactiveSearch will help us to build UI widgets for filters and search-related UI elements. ReactiveMaps will provide us with the UI widgets for Map related UI elements.
ReactiveMaps is currently featured on Product Hunt. 🎉 🎉
Image: A sneak peeks into the UI components offered by ReactiveSearch and ReactiveMaps.

Things we will need

In order to build Airbeds application, we will need a set of things before we get started with writing actual code:
Dataset for Airbeds App:
To make a great UI we should have a good dataset. We found an awesome dataset for our App.
Here is the link to a dataset: https://www.kaggle.com/airbnb/seattle.
ElasticSearch hosting:
You can set up and install an ElasticSearch server by following the official installation guide, or you can create a free account at appbase.io which provides ElasticSearch hosting as a service and is easy to use. For simplicity, we will be using appbase.io service to get started.
I’ve already created an appbase app with Airbeds dataset. You can check out the cleaned-up dataset from above over here in the data browser tool Dejavu, which is built by Appbase.io:
Image: Hosted ElasticSearch dataset for our app. View here
The credentials for accessing the above app programmatically are:
app="airbeds-test-app"
credentials="X8RsOu0Lp:9b4fe1a4-58c6-4089-a042-505d86d9da30" // read-only
Now, we will go step by step to build our application. We’ll use Codesandbox.io. So, you can be with me during the whole journey and see the step by step progress of our application as we build it. Click on the above link and click on Open React button.

Step 1: Base setup for CRA with ReactiveSearch and ReactiveMaps

If you have tried out the Create React App before, you will feel right at home as we build this app.
Create React App
Initialise the CRA setup. We will use npm as the package manager, you can also use yarn instead.
npx create-react-app airbeds
cd airbeds
npm start
Note: npx comes with npm 5.2+ and higher, see instructions for an older release here
Go grab a coffee and be back in a couple of minutes … The setup will be ready for you!
One of the great benefits of using CRA is that it works without requiring to set up a build configuration.
At this point, you should have a directory structure similar to this:
airbeds
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── package-lock.json
├── public
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── App.css
    └── App.js
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js
Next, we will install the ReactiveSearch and ReactiveMaps npm packages.
Install ReactiveSearch
npm install @appbaseio/reactivesearch
Install ReactiveMaps
npm install @appbaseio/reactivemaps
Snippet: Use the button switch and hamburger icon to browse the code we have written so far.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub —  https://github.com/appbaseio-apps/Airbeds-app/tree/step1.

Step 2: Adding components from ReactiveSearch library

Adding the first ReactiveSearch component: ReactiveBase

All the ReactiveSearch components are wrapped inside a container component — ReactiveBase which glues the ElasticSearch index and the ReactiveSearch components together. We’ll use this in /src/App.js:
The app and credentials are taken from my appbase.io app. You can create your own app and add those from your dashboard.
We can set our app’s theme by providing the theme attribute prop to our ReactiveBase component. Here is the theme for our app:
Now let’s start the server with npm start.

Breaking Down The Airbeds App

Now that we have a dataset to play around with and we are also done with our setup, it’s time for adding components in our app.
Before you add the below snippets to the render() method, you should also remember to import them using the following format:
import { Component#1, Component#2 } from @appbaseio/reactivesearch

1. DataSearch Component

DataSearch component creates a search bar UI which allows us to search for available rooms.
In this component, we are passing the dataField parameter with the name value. Here, name is the column in the database on which we want to apply our search. You can learn more about this component here.

2: RangeSlider Component

RangeSlider will be used to create the price filter which allows a user to filter accommodations based on their budgets.
In this component, we are passing the range attribute, which will define the start and end value of our filter. We can set the labels with rangeLabels parameter. We have set default values of start and end price as 10$ and 20$ respectively. range parameter shows the list of components, with RangeSlider component has to change reactively. You can learn more about this component here.

3: NumberBox Component

NumberBox will help us to make UI widget for Guests filter, which allows a user to filter properties by the number of guests that can be accommodated.
Here, data parameter defines the maximum and minimum value for the NumberBox component. You can learn more about this component here.

4. DateRange Component

DateRange will provide UI widget for Date filter, which allows a user to select a range of dates for accommodation.
Here, the numberOfMonths attribute shows the number of months to be shown in the calendar view. initialMonth sets the initial visible month when the calendar UI is opened. You can learn more about this component here.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub project —  https://github.com/appbaseio-apps/Airbeds-app/tree/step2.

Step 3: Styling the components we have so far

Alright, Alright, Alright !!! I got it! You must be thinking that why these components look so simple. Let’s add some styles to them.
We are using the majority of styling for setting layout. We have used flex to design our layout. We have used buttons for each filter. We will show particular filters when the user hovers on particular buttons. Add styles in App.css file and add this statement in App.js file:
import "./App.css";
Snippet: Use the button switch and hamburger icon to browse the code we have written so far.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub —  https://github.com/appbaseio-apps/Airbeds-app/tree/step3.

Step 4: Adding components from ReactiveMaps and styling them

We will import components from ReactiveMaps library using this statement:
import { ReactiveGoogleMap } from '@appbaseio/reactivemaps';

5. ReactiveGoogleMap Component

ReactiveGoogleMap component provides a map as a data-driven layer. One can add marker pins, show popovers, draw polygons, build navigation routes based on the results from the ReactiveSearch components. In our current app, we will display the available accommodations based on the search and filters onto the map view. Interesting! Isn’t it?
In this component, defaultZoom attribute defines the map’s zoom level and accepts integer values between [0, 20]. We can also provide style to ReactiveMap component with the style prop. The innerClass attribute helps us to provide className for inner components of ReactiveMap. renderAllData attribute is used for showing result cards for user’s search. We have designed our result-cards using flex. We will show markers on the map with using renderData parameter. You can know more about this component here.
Wohoo!!! We have made working Airbeds app! But still, we will add more styles to make it look cooler and professional!
Snippet: Use the button switch and hamburger icon to browse the code we have written so far.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub —  https://github.com/appbaseio-apps/Airbeds-app/tree/step4.

Adding the popover effect on markers

Now in the final step #5, we will add a popover effect on markers so that when a user clicks on the marker, we can show them more details. Let’s do it!
We will use onPopoverClick attribute of ReactiveGoogleMap component to achieve this. The return value here is a valid JSX markup, giving you full control over what can be displayed within it. This is how my onPopoverClick function looks:
Congrats! If you have followed along so far, you should see a fully working Airbeds app, just as you saw at the start of the post! 🎉
Snippet: Use the button switch and hamburger icon to browse the code we have written so far.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub —  https://github.com/appbaseio-apps/Airbeds-app/tree/step5.
In case you are missing a step, you can get the code so far by following these:
git clone https://github.com/appbaseio-apps/Airbeds-app.git
cd airbeds
npm install
npm run dev
# open http://localhost:3000

Summary

Here comes the end of our journey, and we have got our awesome Airbeds app built with ReactiveSearch and ReactiveMaps. To summarise everything so far:
This post introduces ReactiveSearch and ReactiveMaps — UI components libraries for ElasticSearch that provide the scaffolding for building great search experiences. Next, we went step-by-step to add different UI components and style our app.

Useful References:

While this post only shows how to build an Airbnb like search, we offer a 5+ hours course teaching on how to build an end-to-end Airbnb clone using React, Redux, TypeScript, Express.JS, ElasticSearch, Firebase and Postgres SQL: https://reactiveapps.io/products/AWtRe_43OSQtLugWf1Fk.
All ReactiveSearch and ReactiveMaps components can be interactively tried using the playground https://opensource.appbase.io/playground/.
The documentation for all the above plus 20 other components is available at https://docs.appbase.io/docs/reactivesearch/v3/overview/quickstart/.
You can look at the code for this app at https://github.com/appbaseio-apps/Airbeds-app.
Finally, go ★ the project on Github so you can find it when you need to build that awesome search!

Published by HackerNoon on 2019/09/11