How To Build A Movie Search App With React and ElasticSearch
We’ve updated this post for 2022 to use the latest React and ReactiveSearch versions, you can read it over here: https://blog.reactivesearch.io/react-search-ui-tutorial
In this post, we will use React and Elasticsearch to build a MovieSearch app. I know you like React, and watching movies, but what is this Elasticsearch thing I’m talking about. Don’t worry. This blog post will give you a kickstart into understanding the basics of Elasticsearch — What is it? Why should you care about it? And, how can you use it with React to build powerful apps painlessly?
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 analyze 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 utilizing its powerful Query DSL. However, setting up Elasticsearch correctly requires a lot of work. For instance, the data mapping, analyzers and tokenizers 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
- A tool to build UI components with an Elasticsearch backend — Reactive Search (we will be using this to build our MovieSearch app’s UI).
In this blog post, with the help of some of these toolings, we will utilize the strengths of Elasticsearch with React to build powerful apps.
How to use Elasticsearch with React?
We will be using ReactiveSearch open-source library to build the MovieSearch app in this post. It offers a range of highly customizable rich UI components that can connect with any Elasticsearch server and provide you with a good default queries for all generic use-cases (think E-commerce, Aggregators, Events et al) bundled into these components. ReactiveSearch will help us to build UI widgets for filters and search-related UI elements.
In the second part of the tutorial, I will show how to use Server Side Rendering (aka SSR) with Next.js to instantly load our Movie Search UI and also get some sweet SEO benefits.
You can try out the SSR enabled Live Demo here.
Things we will need
In order to build MovieSearch app, we will need a set of things before we can get started with writing the actual code —
Dataset for MovieSearch App
To make a great UI we should have a good dataset. We found an awesome dataset for our MovieSearch App. Here is the link to the dataset: https://www.kaggle.com/rounakbanik/the-movies-dataset.
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 with.
I’ve already created an appbase app with the MovieSearch dataset indexed in it. You can browse it with dejavu over here:
The URL of the above app is:
app="movie_app_final"
url="https://7fdc8bd59c19:7b573cb7-5bb1-491a-b298-a03ad86970c9@arc-cluster-appbase-demo-6pjy6z.searchbase.io"
Now, we will go step-by-step and build our application. We’ll use Codesandbox.io to generate code at each intermediate step, making it easy to test. Click on the above link and click on Open React
button.
Step 1: Base setup for CRA with ReactiveSearch
If you have tried out the Create React App before, you will feel right at home as we build this app.
Create React App
Initialize the CRA setup. We will use npm
as the package manager, you can also use yarn
instead.
npx create-react-app moviesearch
cd moviesearch
npm start
Note:
npx
comes with npm 5.2+ and higher, see instructions for an older release here.
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:
moviesearch
├── 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
Install ReactiveSearch
Next, we will install ReactiveSearch.
npm install @appbaseio/reactivesearch
In addition to the code sandbox above, you can also try the code so far directly from our GitHub — https://github.com/appbaseio-apps/MovieSearch-app/tree/step1.
Step 2: Setup with DataSearch and all the filter components from ReactiveSearch
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 url
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 theme
attribute prop
to our ReactiveBase component. Here, we will use this to give our app a night mode look:
Now let’s start the server with npm start
.
Breaking Down The MovieSearch App
To add any component, we have to first import it from the ReactiveSearch library using this statement:
import { component-name } from '@appbaseio/reactivesearch';
Component #1: DataSearch
DataSearch
component creates a search bar UI which allows us to search for movies.
In this component, we are passing the dataField
prop with original_title.search
value. Here,original_title
is the name of the field in the app on which we want to apply our search.
queryFormat sets the query’s format. It can have values of or or and. or returns all the results matching any of the search query text’s parameters. For example, searching for “bat man” with or will return all the results matching either “bat” or “man”. On the other hand with and, only results matching both “bat” and “man” will be returned. It returns the results matching all of the search query text’s parameters.
You can learn more about this component over here.
Component #2: MultiList
We will create a genre-based filterable UI component using MultiList
.
In this component, we are passing genres_data as the dataField, the .raw
suffix signifies that we are using the Keyword type (over the Text type) which is suitable for performing an aggregation. Another interesting prop here is react. It specifies the components to watch for when updating the current MultiList’s data view. For example: If we search for “Bat man”, the MultiList’s view will also be simultaneously updated to only show results that match the search query. The showCount prop controls whether to show the count values next to each item. The innerClass prop allows us to set CSS styles to particular elements within the component. You can learn more about this component here.
Component #3: SingleRange
We will use the SingleRange
component to create a revenue filter UI widget.
Here, we are passing the data parameter, in which we will give different options with start and end values for revenue. Other parameters are self-explanatory. You can learn more about this component here.
Component #4: RangeSlider
RangeSlider
will help us to make a UI widget for a ratings based filter.
Here, we are passing range prop as an object with start
and end
keys. You can learn more about it here.
Component#5: MultiDataList
MultiDataList
will help us make a UI a language-based filter.
In contrast to MultiList, we also pass a data
prop to MultiDataList which is used for displaying the filter options. You can learn more about MultiDataList over here.
Component#6: DateRange
We will use the DateRange
component to create a filter for movie release dates.
In DateRange, we will just be passing the obvious props. It goes without saying that the dataField
prop for DateRange expects a field of Date
type. You can learn more about DateRange component over here.
In addition to the above code sandbox, you can also try the code so far directly from our GitHub repo — https://github.com/appbaseio-apps/MovieSearch-app/tree/step2.
Step 3: Styling the components we have so far
Now that we have added all the filter components with DataSearch component, it’s time to style them!
We are using the majority of styling for setting the layout. We will use flex
to design our layout. We will create a leftbar
div, which will contain all of our filter components. Also, we have added styles for the top navigation bar, which contains the DataSearch component. We have used innerClass
property of each component to style the inner parts of it.
You can copy the CSS styles from here and add them to App.css
and import it in your App.js
with a import './App.css'
statement along with our other imports. That’s all!
In addition to the code sandbox above, you can also try the code so far directly from our GitHub repo — https://github.com/appbaseio-apps/MovieSearch-app/tree/step3.
Step 4: Adding ReactiveList component and making our app responsive
Component#7: ReactiveList
And finally, we will use the ReactiveList component to show the movies that match our search and filters in a fancy card-based view.
The pagination
and paginationAt
props determine whether we will use pagination (or an infinite scroll) to display our results and when using pagination, where the position of the pagination component would be at. We have set it to bottom
. You can also try passing top
or both
.
The resultStats
prop which will show the number of movies in the result and other statistical information of result. sortOptions
will provide options to sort results by their popularity, alphabetic order and ratings. You can also add more sort options depending on your data. You can learn more about the ReactiveList component over here.
Next, we will make our app responsive so that it looks good in any size of the screen. We will use a toggle button for smaller screens so that the user can switch between the results view of movies and the filters view. Here, I have used a state variable isClicked
to decide which view should be displayed.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub —https://github.com/appbaseio-apps/MovieSearch-app/tree/step4.
Step 5: Adding overlay effect on result cards
Now in the final step, we will add a fancy overlay effect on result cards so that users can view the movie information by hovering over them.
In addition to the code sandbox above, you can also try the code so far directly from our GitHub —https://github.com/appbaseio-apps/MovieSearch-app/tree/step5.
If you have been running the setup locally, you can open the app in the browser after applying the above changes:
npm start
# open http://localhost:3000
You should see the app running. Now search for your favourite movies and enjoy!
Woohoo!!! We made it! We have made a beautiful MovieSearch App! We went from a boilerplate with CRA to creating a MovieSearch UI, hopefully well within an hour.
Bonus Step: Using SSR with next.js
If you have come this far, ReactiveSearch also allows performing server-side rendering (aka SSR). We will use the next.js library to showcase this!
You can read the following article about the history of SSR with ReactiveSearch and how it enables you to build a blazing fast search UI besides giving some sweet SEO benefits.
As a first step, install next.js in your project:
npm install --save next
Make sure you add a script to your package.json like this:
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
Usage
First, import initReactivesearch
:
import initReactivesearch from '@appbaseio/reactivesearch/lib/server';
Then, evaluate the initial state:
const initialState = await initReactivesearch(...);
and finally, pass the computed initial state to ReactiveBase
component.
<ReactiveBase {...props} initialState={initialState}>
...
</ReactiveBase>
If you got stuck somewhere, you can check out the details about SSR with ReactiveSearch over here. Now, create a directory named pages in your root directory and move all the JS files in it. Create another directory named static in the root directory to store our app’s logo and other image files we have used. Change _document.js file as it is mentioned in the above link.
And we are done! Just run this command:
npm run dev
And you will see the MovieSearch app with fast rendering at http://localhost:3000. Try to refresh the page to see the effect of next.js.
In case you are missing a step, you can get the code so far by following these:
git clone https://github.com/appbaseio-apps/MovieSearch.git
cd moviesearch
npm install
npm run dev
# open http://localhost:3000
Summary
Here comes the end of our journey and we have got our awesome MovieSearch app built with ReactiveSearch. To summarize our journey:
This post introduces Elasticsearch and ReactiveSearch — A UI components library written in React for building search UIs. We jump through the hoops in a step-by-step manner to build our app.
- Step 1: Base setup of CRA with ReactiveSearch (Codesandbox link: step1)
- Step 2: Setup with DataSearch and all the filter components from ReactiveSearch (Codesandbox link: step2)
- Step 3: Styling the components we have so far (Codesandbox link: step3)
- Step 4: Adding ResultCard component and making our app responsive (Codesandbox link: step4)
- Step 5: Adding overlay effect on result-cards (Codesandbox link: step5)
Using about 8 components, we were able to build a nice looking MovieSearch UI!
In the bonus step, we add SSR using next.js to enable a faster first paint (almost instantaneous) along with getting some sweet SEO benefits when running the app in a production setting.
Useful References
All ReactiveSearch 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/ .
You can look at the code for this app at https://github.com/appbaseio-apps/MovieSearch
Finally, go ★ the project on Github so you can find it when you need to build that awesome search!