Use MultiSearch Js API in a React Native application

Take benefit from MultiSearch Js API in a React Native application.

  1. Import Multisearch JS library in React Component and Integrate it in the app
  2. How-to use the Js library in a react native app
  3. 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
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.

Configure the Js library

First, the Woosmap MultiSearch Js library has to be configured and callbacks have to be defined:

tsx
        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

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",
  },
});

    
Was this article helpful?
Have more questions? Submit a request