Step 0: Install ReactiveSearch Native
If you have an existing project, you can install reactivesearch-native
module using yarn or npm.
yarn add @appbaseio/reactivesearch-native
or
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.
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.
npm install -g expo-cli
Create sample application using expo-cli
expo init BookSearch
cd BookSearch
Install the @appbaseio/reactivesearch-native
repo.
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.
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.
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.
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.
<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.
<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:
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.
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: