Step 0: Install ReactiveSearch Native

If you have an existing project, you can install reactivesearch-native module using yarn or npm.

Copy
yarn add @appbaseio/reactivesearch-native

or

Copy
npm install @appbaseio/reactivesearch-native

If you are starting from scratch, follow the next steps on getting started with reactivesearch-native.

Step 1: Create Boilerplate with Expo CLI

We will create a search UI based on a books dataset with ReactiveSearch components.

Image

Caption: Final image of how the app will look.

For this quickstart guide, we will use Expo CLI and Expo client.

Note

In order to use latest expo CLI, make sure you are using Node version >=10

Install expo-cli globally.

Copy
npm install -g expo-cli

Create sample application using expo-cli

Copy
expo init BookSearch
cd BookSearch

Install the @appbaseio/reactivesearch-native repo.

Copy
yarn add @appbaseio/reactivesearch-native

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 good-books-ds and the associated read-only credentials are nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d. You can browse and clone the dataset into your own app from here.

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

Copy
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { ReactiveBase } from '@appbaseio/reactivesearch-native';

export default class App extends React.Component {
	render() {
		return (
			<ReactiveBase
				app="good-books-ds"
				credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d"
			>
				<View style={styles.container}>
					<Text>Hello ReactiveSearch!</Text>
				</View>
			</ReactiveBase>
		);
	}
}

const styles = StyleSheet.create({
	container: {
		flex: 1,
		alignItems: 'center',
		justifyContent: 'center',
	},
});

This is how the app should look after running the yarn start command.

Screenshot

Step 3: Adding Filter and Result Components

For this app, we will be using DataSearch component for filtering the dataset and ReactiveList component for showing the search results.

Lets add them within the ReactiveBase component. But before we do that, lets look at the important props for each.

Copy
<DataSearch
	componentId="searchbox"
	dataField={['original_title', 'original_title.search', 'authors', 'authors.search']}
	placeholder="Search for books"
/>

The DataSearch component we describe above creates a searchbox UI component that queries on the specifield dataField(s) in the dataset.

Next, we need a component to show the matching results. ReactiveList does exactly this.

Copy
<ReactiveList
	componentId="results"
	dataField="original_title"
	size={7}
	showResultStats={false}
	pagination={true}
	react={{
		and: 'searchbox',
	}}
	onData={res => (
		<View style={styles.result}>
			<Image source={{ uri: res.image }} style={styles.image} />
			<View style={styles.item}>
				<Text style={styles.title}>{res.original_title}</Text>
				<Text>{res.authors}</Text>
			</View>
		</View>
	)}
/>

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.

ReactiveSearch uses native-base which uses some fonts which can be included by adding:

Copy
import { Font } from 'expo'
async componentWillMount() {
	await Font.loadAsync({
		Roboto: require('native-base/Fonts/Roboto.ttf'),
		Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
		Ionicons: require('native-base/Fonts/Ionicons.ttf'),
	});
}

Now, we will put all the things together to create the final view.

Copy
import React from 'react';
import { StyleSheet, Text, View, ScrollView, Image } from 'react-native';
import { ReactiveBase, DataSearch, ReactiveList } from '@appbaseio/reactivesearch-native';

export default class App extends React.Component {
	constructor() {
		super();
		this.state = {
			isReady: false,
		};
	}

	async componentWillMount() {
		await Expo.Font.loadAsync({
			Roboto: require('native-base/Fonts/Roboto.ttf'),
			Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
			Ionicons: require('native-base/Fonts/Ionicons.ttf'),
		});

		this.setState({ isReady: true });
	}

	render() {
		if (!this.state.isReady) {
			return (
				<View style={styles.container}>
					<Text>Loading...</Text>
				</View>
			);
		}

		return (
			<ReactiveBase
				app="good-books-ds"
				credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d"
			>
				<ScrollView>
					<View style={styles.container}>
						<DataSearch
							componentId="searchbox"
							dataField={[
								'original_title',
								'original_title.search',
								'authors',
								'authors.search',
							]}
							placeholder="Search for books"
						/>
						<ReactiveList
							componentId="results"
							dataField="original_title"
							size={7}
							showResultStats={false}
							pagination={true}
							react={{
								and: 'searchbox',
							}}
							onData={res => (
								<View style={styles.result}>
									<Image source={{ uri: res.image }} style={styles.image} />
									<View style={styles.item}>
										<Text style={styles.title}>{res.original_title}</Text>
										<Text>{res.authors}</Text>
									</View>
								</View>
							)}
						/>
					</View>
				</ScrollView>
			</ReactiveBase>
		);
	}
}

const styles = StyleSheet.create({
	container: {
		padding: 10,
		marginTop: 25,
	},
	image: {
		width: 100,
		height: 100,
	},
	result: {
		flexDirection: 'row',
		width: '100%',
		margin: 5,
		alignItems: 'center',
	},
	item: {
		flexDirection: 'column',
		paddingLeft: 10,
	},
	title: {
		fontWeight: 'bold',
	},
});

If you have followed along so far, you should be able to see the final app:

Image