ReactiveSearch Quickstart

Step 0: Create Boilerplate with CRA

In this section, we will create a search UI based on a cars 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.

create-react-app my-awesome-search && cd my-awesome-search

Step 1: Install ReactiveSearch

We will fetch and install reactivesearch module using yarn or npm.

yarn add @appbaseio/reactivesearch

or

npm install @appbaseio/reactivesearch

Step 2: Adding the 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 carstore-dataset and the associated read-only credentials are 4HWI27QmA:58c731f7-79ab-4f55-a590-7e15c7e36721. 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.

import React, { Component } from 'react';
import { ReactiveBase } from '@appbaseio/reactivesearch';

class App extends Component {

	render() {
		return (
			<ReactiveBase
				app="carstore-dataset"
				credentials="4HWI27QmA:58c731f7-79ab-4f55-a590-7e15c7e36721">
				// 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 Result Components

For this app, we will be using CategorySearch and SingleRange components for filtering the dataset. And ResultCard 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.

<CategorySearch
	componentId="searchbox"
	dataField="model"
	categoryField="brand.keyword"
	placeholder="Search for cars"
/>

The CategorySearch component we describe above creates a searchbox UI component that queries on the name field in the dataset and shows categorizations using the brand.raw field in the dataset. Here is how it will look visually.

Note: If you cloned your own dataset, the field will be called brand.keyword instead of brand.raw.

Next, we will look at the SingleRange component for creating a ratings based filter.

<SingleRange
	componentId="ratingsfilter"
	dataField="rating"
	title="Filter by ratings"
	data={[
		{"start": 4, "end": 5, "label": "4 stars and up"},
		{"start": 3, "end": 5, "label": "3 stars and up"}
	]}
	defaultValue="4 stars and up"
/>

SingleRange filters the DB by rating field based on the UI choice the user makes. We also set the 4 stars and up option to be default selected when the UI loads up first.

Finally, we need a component to show the matching results. ResultCard does exactly this.

<ReactiveList
	componentId="results"
	dataField="name"
	size={6}
	pagination={true}
	react={{
		and: ["searchbox", "ratingsfilter"]
	}}
	render={({ data }) => (
		<ReactiveList.ResultCardWrapper>
            {
                data.map(item => (
                    <ResultCard key={item._id}>
										<ResultCard.Image 
											src='http://www.asfera.info/files/images/
											1_aprela/4/deloreyn.jpg'
										/>
                        <ResultCard.Title 
                            dangerouslySetInnerHTML={{ 
                                __html: item.name 
                            }} 
                        />
                        <ResultCard.Description>
                           {item.brand + " " + "*".repeat(item.rating)}
                        </ResultCard.Description>
                    </ResultCard>
                ))
            }
        </ReactiveList.ResultCardWrapper>
	)}
/>

The react prop here specifies that it should construct a query based on the current selected values of searchbox and ratingsfilter components. Every time the user changes the input 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 ResultCard component’s UI would look like.

Now, we will put all three components together to create the UI view.

import React, { Component } from 'react';
import { 
	ReactiveBase, CategorySearch, SingleRange, ResultCard, ReactiveList 
} from '@appbaseio/reactivesearch';

class App extends Component {
	render() {
		return (
				<ReactiveBase
				app="carstore-dataset"
				credentials="4HWI27QmA:58c731f7-79ab-4f55-a590-7e15c7e36721">
					<CategorySearch
						componentId="searchbox"
						dataField="model"
						categoryField="brand.keyword"
						placeholder="Search for cars"
					/>
					<SingleRange
						componentId="ratingsfilter"
						title="Filter by ratings"
						dataField="rating"
						data={[
							{"start": "4", "end": "5", "label": "4 stars and up"},
							{"start": "3", "end": "5", "label": "3 stars and up"},
							{"start": "2", "end": "5", "label": "2 stars and up"},
							{"start": "1", "end": "5", "label": "see all ratings"},
						]}
						defaultValue="4 stars and up"
					/>
					<ReactiveList
						componentId="result"
						title="Results"
						dataField="model"
						from={0}
						size={5}
						pagination={true}
						react={{
							and: ["searchbox", "ratingsfilter"]
						}}
						render={({ data }) => (
							<ReactiveList.ResultCardWrapper>
								{
									data.map(item => (
										<ResultCard key={item._id}>
											<ResultCard.Image 
												src='https://bit.do/demoimg'
											/>
											<ResultCard.Title 
												dangerouslySetInnerHTML={{ 
													__html: item.model 
												}} 
											/>
											<ResultCard.Description>
												{item.brand + " " + "*".repeat(item.rating)}
											</ResultCard.Description>
										</ResultCard>
									))
								}
							</ReactiveList.ResultCardWrapper>
						)}
					/>
				</ReactiveBase>
		);
	}
}

export default App;

If you have followed along so far, you should a screen similar to:

Image

We have built our entire search UI in just 50 lines!

The only thing missing at this point is the layout, ReactiveSearch doesn’t use a layout system internally. For example, if you are using a grid from Bootstrap or Materialize, you can use that to style the layout. Or if you prefer to use Flex, you can use that.


Step 4: Adding a Layout Grid with Flex

For this quickstart, we will use a Flex based layout. If you are new to Flex, I recommend a quick read of this article.

With ~16 more lines of inline styles, here is our final app layout.

import React, { Component } from 'react';
import { ReactiveBase, CategorySearch, SingleRange, ReactiveList } from '@appbaseio/reactivesearch';

class App extends Component {
	render() {
		return (
				<ReactiveBase
				app="carstore-dataset"
				credentials="4HWI27QmA:58c731f7-79ab-4f55-a590-7e15c7e36721">
					<div style={{ display: "flex", flexDirection: "row" }}>
						<div style={{ display: "flex", flexDirection: "column", width: "40%" }}>
							<CategorySearch
								componentId="searchbox"
								dataField="model"
								categoryField="brand.keyword"
								placeholder="Search for cars"
								style={{
									padding: "5px",
									marginTop: "10px"
								}}
							/>
							<SingleRange
								componentId="ratingsfilter"
								title="Filter by ratings"
								dataField="rating"
								data={[
									{"start": "4", "end": "5", "label": "4 stars and up"},
									{"start": "3", "end": "5", "label": "3 stars and up"},
									{"start": "2", "end": "5", "label": "2 stars and up"},
									{"start": "1", "end": "5", "label": "see all ratings"},
								]}
								defaultValue="4 stars and up"
								style={{
									padding: "5px",
									marginTop: "10px"
								}}
							/>
						</div>
						<ReactiveList
							componentId="result"
							title="Results"
							dataField="model"
							from={0}
							size={6}
							pagination={true}
							react={{
								and: ["searchbox", "ratingsfilter"]
							}}
							style={{
								width: "60%",
								textAlign: "center"
							}}
							render={({ data }) => (
								<ReactiveList.ResultCardWrapper>
									{
										data.map(item => (
											<ResultCard key={item._id}>
												<ResultCard.Image 
													src='https://www.enterprise.com/content/dam/global-vehicle-images/cars/FORD_FOCU_2012-1.png'
												/>
												<ResultCard.Title 
													dangerouslySetInnerHTML={{ 
														__html: item.model 
													}} 
												/>
												<ResultCard.Description>
												{item.brand + " " + "*".repeat(item.rating)}
												</ResultCard.Description>
											</ResultCard>
										))
									}
								</ReactiveList.ResultCardWrapper>
							)}
						/>
					</div>
				</ReactiveBase>
		);
	}
}

export default App;

If you have followed along, this is how our app should look now.

For convenience, you can checkout the final code from the ReactiveSearch starter github repo - https://github.com/appbaseio-apps/reactivesearch-starter-app.

You can run it with the following commands:

git clone https://github.com/appbaseio-apps/reactivesearch-starter-app
cd reactivesearch-starter-app
yarn && yarn start
# open http://localhost:3000 and you should see the app.
# The magic sauce is inside **src/App.js** file.

Step 5: ReactiveSearch as UMD

It is also possible to run ReactiveSearch without relying on a Node.JS environment tooling for the build setup. Here, I am using v2.0.0, this can be replaced with the version you are using.

<script src="https://cdn.rawgit.com/appbaseio/reactivesearch/v2.0.0/packages/web/umd/reactivesearch.js"></script>

A GZip version (131KB in size) is also available at https://cdn.rawgit.com/appbaseio/reactivesearch/v2.0.0/packages/web/umd/reactivesearch.js.gzip.

The ReactiveSearch starter project has also been built with the UMD version of the lib, and is available at https://github.com/appbaseio-apps/reactivesearch-starter-app/tree/umd.

You can run it with the following commands:

git clone https://github.com/appbaseio-apps/reactivesearch-starter-app
cd reactivesearch-starter-app
git checkout umd    # where we have the umd version of the starter app
python -m SimpleHTTPServer 1234   # now open http://localhost:1234

🆕Visit our new docs available at docs.appbase.io