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"]
    }
  },
  address: {
    key: "woos-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // your woosmap project public key
    params: {
      components: {country: ["FR", "GB"]},
      language: "en",
        }
      },
      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","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"]
        }
      },
      address: {
        key: "woos-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // your woosmap project public key
        params: {
          components: {country: ["FR", "GB"]},
          language: "en",
        }
      },
      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