Use MultiSearch Js API in a React Native application
Take benefit from MultiSearch Js API in a React Native application.
- Import Multisearch JS library in React Component and Integrate it in the app
- How-to use the Js library in a react native app
- Working Sample
Import Multisearch JS library in React Component and Integrate it in the app
Multisearch React component is a wrapper around the javascript version of SDK. It has a dependency
on react-native-webview. Please add webview dependency by
installing it using npm i react-native-webview
.
Add MultisearchView.tsx
in your project (copy paste the code below) to start using the Multisearch library.
MultisearchView.tsx
import * as React from "react";
import {useImperativeHandle} from "react";
import {WebView} from "react-native-webview";
export interface WoosData {
api: string;
description: string;
id: string;
item: Object;
matched_substrings: null;
types: [string];
}
export interface MultisearchViewProps {
onAutocompleteMulti?(results: [Object], error?: any);
onDetailsMulti?(results: Object, error?: any);
config: JSON;
}
const MultisearchView = (props: MultisearchViewProps, ref) => {
const webviewRef = React.useRef<WebView>(null);
useImperativeHandle(ref, () => ({
autocompleteMulti: (searchfor: string) => {
if (searchfor === "") {
props.onAutocompleteMulti(Object[0], null);
} else {
if (webviewRef) {
const search_data = { action: "search", text: searchfor };
webviewRef.current.postMessage(JSON.stringify(search_data));
}
}
},
detailsMulti: (api: string, id: string) => {
if (webviewRef) {
const search_data = { action: "detail", api: api, id: id };
webviewRef.current.postMessage(JSON.stringify(search_data));
}
},
}));
React.useEffect(() => {
return () => {
console.log("Component dismiss: MultiSearchView");
};
}, []);
function onMessage(data) {
const communication = JSON.parse(data.nativeEvent.data);
const results = communication["results"];
const error = communication["error"];
if (communication["api"] == "search") {
if (props.onAutocompleteMulti) {
props.onAutocompleteMulti(results, error);
}
} else if (communication["api"] == "detail") {
if (props.onDetailsMulti) {
props.onDetailsMulti(results, error);
}
}
}
const HTML = `
<html>
<body>
<script type="text/javascript" src="https://sdk.woosmap.com/multisearch/multisearch.js"></script>
<script>
var multisearchObj = woosmap.multisearch(`${JSON.stringify(props.config)}`);
let hook = navigator.appVersion.includes('Android') ? document: window;
hook.addEventListener("message", message => {
if(message.data){
try {
var action = JSON.parse(message.data);
if(action["action"] == "search"){
if(action["text"]){
var searchText = action["text"];
multisearchObj.autocompleteMulti(searchText, function (error, results) {
let output = {"api":"search","error":error,"results":results}
window.ReactNativeWebView.postMessage(JSON.stringify(output));
});
}
}
else if(action["action"] == "detail"){
let api = action["api"];
let id = action["id"];
multisearchObj.detailsMulti({ id, api }, function (error, result) {
let output = {"api":"detail","error":error,"results":result}
window.ReactNativeWebView.postMessage(JSON.stringify(output));
});
}
}
catch(err) {
console.log(err.message);
}
}
});
</script>
<h1>hi</h1>
</body>
</html>`;
const renderHtml = {html: HTML, baseUrl: "http://localhost"}
return (<WebView ref={webviewRef}
originWhitelist={["*"]}
scalesPageToFit={false}
mixedContentMode="compatibility"
source={renderHtml}
onMessage={onMessage}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
style={{height: 0}}/>
);
};
export default React.forwardRef(MultisearchView);
How-to use the Js library in a react native app
The MultisearchView component exposes three props.
config
: Parameter used to configure multi-search SDK. For more information, follow linkonAutocompleteMulti
(Optional): function returning callback when any search result is available from SDK. This function has a signature asonAutocompleteMulti?(results: [Object], error?: any)
.onDetailsMulti
(Optional): function returning callback when asking for any particular places and results from SDK. This function has a signature asonDetailsMulti?(results: Object, error?: any)
.
Configure the Js library
First, the Woosmap MultiSearch Js library has to be configured and callbacks have to be defined:
import MultisearchView from "./multisearch/MultisearchView";
let multisearchref = React.useRef(null);
let multisearchConfig: JSON = {
debounceTime: 0,
apiOrder: ["localities", "address", "places"],
localities: {
key: "woos-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // your woosmap project public key
params: {
components: {country: ["FR", "GB"]},
language: "en",
types: ["locality", "country", "postal_code"]
}
},
store: {
key: "woos-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // your woosmap project public key
params: {
query: 'type:"bose_store"'
}
},
places: {
key: "{your_google_api_key}",
params: {
components: {country: ["FR", "GB"]}
}
}
}
<MultisearchView
ref={multisearchref}
config={multisearchConfig} // share the json with all parameters here
onAutocompleteMulti={onSearch} // autocomplete callback that provide you autocomplete suggestions
onDetailsMulti={onDetail} // get detail callback that provide you additionnal details for a specific suggestion
/>
More information about the configuration of the library in the JavaScript API section
Retrieve suggestions
You can retrieve suggestions from the user input by calling the autocompleteMulti() method:
multisearchref.current.autocompleteMulti(searchText);
A standardised JSON response is returned through the onAutocompleteMulti
callback with all that’s needed to highlight what matches your users’ searches.
Get Details
Finally, to get the suggestion details when a user selects one from the pick list, call the details() method:
multisearchref.current.detailsMulti(suggestion.api, suggestion.id);
This method is needed to retrieve accurate locations for every suggestion and pass structured address components, whatever the place your users looked for. A standardised JSON response is returned through the onDetailsMulti
callback.
Working Sample
IntegrationMultiSearchSDK.tsx
import * as React from "react";
import {
StyleSheet,
View,
Text,
TextInput,
TouchableHighlight,
FlatList,
TouchableOpacity,
Alert,
Platform,
} from "react-native";
import {LogBox} from "react-native";
import MultisearchView, {
WoosData,
} from "./MultisearchView";
export default function IntegrationMultiSearchSDK() {
const [searchText, setSearchText] = React.useState("");
const [data, setData] = React.useState<WoosData | null>(null);
let multiSearchref = React.useRef(null);
React.useEffect(() => {
LogBox.ignoreLogs(["VirtualizedLists should never be nested"]);
return () => {
console.log("Component dismiss: IntegrationWebview");
};
}, []);
const onChangeSearchText = (value: string) => {
setSearchText(value);
};
const onPress = () => {
multiSearchref.current.autocompleteMulti(searchText);
};
const onClickList = (api, id) => {
multiSearchref.current.detailsMulti(api, id);
};
const onSearch = (results, error) => {
if (error) {
console.error(error);
}
setData(results);
};
const onDetail = (results, error) => {
if (error) {
console.error(error);
}
Alert.alert("Details", JSON.stringify(results));
};
const multisearchConfig: JSON = {
debounceTime: 0,
apiOrder: ["localities", "places"],
localities: {
key: "woos-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // your woosmap project public key
params: {
components: {country: ["FR", "GB"]},
language: "en",
types: ["locality", "country", "postal_code"]
}
},
store: {
key: "woos-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // your woosmap project public key
params: {
query: 'type:"bose_store"'
}
},
places: {
key: "{your_google_api_key}",
params: {
components: {country: ["FR", "GB"]}
}
}
}
return (
<View style={pageStyles.main}>
<View style={pageStyles.row}>
<Text>Search</Text>
<MultisearchView
ref={multiSearchref}
onAutocompleteMulti={onSearch}
onDetailsMulti={onDetail}
config={multisearchConfig}
></MultisearchView>
</View>
<View style={pageStyles.row}>
<TextInput
style={pageStyles.input}
onChangeText={onChangeSearchText}
value={searchText}
placeholder="Text"
keyboardType="default"
autoCapitalize="none"
autoComplete={Platform.OS === "web" ? "none" : "off"}
/>
<TouchableHighlight
activeOpacity={0.6}
underlayColor="#DDDDDD"
onPress={onPress}
>
<View style={pageStyles.button}>
<Text style={pageStyles.text}>Search</Text>
</View>
</TouchableHighlight>
</View>
<View style={pageStyles.row}>
<SearchList
searchList={data}
searchText={searchText}
onDetail={onClickList}
/>
</View>
<View style={pageStyles.row}></View>
</View>
);
}
export function SearchList({searchList, searchText, onDetail}) {
const Item = ({title}) => (
<View style={pageStyles.item}>
<Text style={pageStyles.searchtitle}>{title}</Text>
</View>
);
const EmptyResult = () => (
<View style={pageStyles.row}>
{searchText ? (
<Text style={pageStyles.resulttitle}>No result found.</Text>
) : (
<Text style={pageStyles.resulttitle}>Search in above box.</Text>
)}
</View>
);
const SummaryResult = () => (
<View style={pageStyles.row}>
{searchList && searchList.length > 0 && (
<View style={pageStyles.row}>
<Text style={pageStyles.resulttitle}>
Result found : {searchList.length}
</Text>
</View>
)}
</View>
);
function actionOnRow(item) {
onDetail(item["api"], item["id"]);
}
const renderItem = ({item}) => (
<TouchableOpacity onPress={() => actionOnRow(item)}>
<View>
<Item title={item.description}/>
</View>
</TouchableOpacity>
);
return (
<View style={pageStyles.row}>
<FlatList
data={searchList}
renderItem={renderItem}
keyExtractor={(searchList) => searchList.id}
ListEmptyComponent={EmptyResult}
ListHeaderComponent={SummaryResult}
/>
</View>
);
}
const pageStyles = StyleSheet.create({
main: {
flex: 1,
overflow: "scroll",
minHeight: 100,
marginVertical: 10,
paddingLeft: 5,
paddingRight: 5,
},
row: {
paddingBottom: 5,
},
button: {
alignItems: "center",
backgroundColor: "blue",
padding: 10,
borderRadius: 10,
},
text: {
alignItems: "center",
color: "white",
fontWeight: "bold",
},
input: {
height: 40,
margin: 0,
marginBottom: 5,
borderWidth: 1,
borderRadius: 5,
padding: 10,
backgroundColor: "white",
},
item: {
backgroundColor: "#f9c2ff",
padding: 10,
marginVertical: 2,
marginHorizontal: 10,
},
searchtitle: {},
resulttitle: {
fontWeight: "bold",
},
});