Using react instantsearch for react native

Hi, I am new to algolia, and I read through docs some of it. I followed this guide but I have some questions: https://community.algolia.com/react-instantsearch/Getting_started_React_native.html#install-react-instantsearch

My question is on the Hits component. It seems that displaying a list of records (lets say list of users) the data is being taken from Algolia database/index. I was wondering what If I want to use only the SearchBox and query from algolia when search happens only. Now I’m not sure if this is possible or whether its done that way for a better perfomance. Looking for insights regarding this.

Also, in the component InstantSearch, the appId and apiKey should be provided there. isn’t it supposed to be hidden from front-end code!?

One last thing, in Hits component, specifically connectInfiniteHits which has a function that’s called refine() when page reaches the end to fetch more data. Where is the limit is set (fetches per page)? is it set while setting the index ?

Hi @sherzad,

I’m not sure to fully understand your first point. You don’t want to display the results immediately? What is the behaviour that you expect? With the connectors API you can customise the widgets to your needs. Take a look at connectStateResults, we also have a guide on conditional display in our documentation.

For the concern about the privacy of the keys, the appId can be public without any trouble. For the apiKey there is two types of keys created by default when you create an account at Algolia. The first one is the “Admin API Key”, this one must never be shared or present in your front end code. It’s used to configure & push data to your index. The second one is the “Search-Only API Key”. This one can be public you can only query the data from your index. You can find more informations about the API keys in our documentation.

For you last point you can configure the number of hits per page at indexing time and query time. At indexing time you need to pass the hitsPerPage parameter to the setSettings method of the client. You can also override it at query time. With React InstantSearch you can achieve this with the Configure widget.

<InstantSearch>
  <Configure hitsPerPage="50" />
</InstantSearch>

Hope that helps! Let me know if you have questions :wink:

Hi @samuel.vaillant

I followed the tutorial (https://community.algolia.com/react-instantsearch/Getting_started_React_native.html) but I have come across a problem. the <SearchBox> component pushes flatlist items out of the screen view (last 2 items in the list cannot be seen)

<View style={{flex: 1}}>
     <InstantSearch
         appId='....'
         apiKey='...'
         indexName='users'
      >
            <View style={{flexDirection: 'row'}}>
               <SearchBox />
            </View>
            <Hits/>                
      </InstantSearch>
</View>

Screenshot from 2017-12-23 13-18-30

Hi @sherzad,

It’s something related to this issue #285. The InstantSearch root component doesn’t take all the space available and so the layout is broken. This issue will be fix in the coming days, we have a PR waiting for review that aims to fix the issue by providing a way to customise the root component. Then you will be able to pass some styling to the root component (like flex: 1).

But for now as a workaround you can add a paddingBottom to your FlatList with the props contentContainerStyle to avoid the parent element to crop the content. You will have something like:

<FlatList
  contentContainerStyle={{
    paddingBottom: 20 // customise to your needs
  }}
/>

Thank you for your reply @samuel.vaillant,

Yup, I went for a dirty hack at the moment, wanted to ask regarding offline capabilities. is it possible to have offline search in react native!

I noticed that there is an offline mode sdk for ios and android (will having this requires any package membership ?), so I’m wondering if it’s gonna be possible to implement.

Hi @sherzad,

With the JavaScript ecosystem it’s not something doable I think. You can persist the results of Algolia in localStorage but you can’t have the offline search experience.

But since React Native can use natives modules, it could be interesting to use the iOS & Android version of InstantSearch instead of the JavaScript one. Not sure that it will work though, I reach the mobile team for gather their feedbacks.

cc @guy.daher @pln

Hi @samuel.vaillant,
First of all, Happy new year :slight_smile:

I am eagerly waiting for the mobile team to respond regarding the offline search capabilities. Meanwhile, I came across another problem, I am trying to exclude a record from showing in the search results. I went through the docs but I couldn’t find an option for that.

I am trying to exclude the current user record from appearing in the Hits ! wondering how to accomplish that?

Hi @sherzad,

Thanks, happy new year to you too :wink:

You can do it with two different ways, the first solution is to use the Configure widget combine with the negative filters. But since those filters are set at query time the user can still modify the query to see all the results. In your case it’s not a big deal since you hide the results from the current user.

But for some other use cases we have the “Secured API Keys”, it’s an API Key that you generate from the backend and then use from the front end to restrict some data to your users. You can’t override the filters set on the key at query time. You can find more informations about that in our documentation.

Hope that helps :slightly_smiling_face:

Hi @sherzad,

I have some news regarding the offline search capabilities, it seems possible to do with React Native but we never tested it though. So it should be possible but we still have a some concern regarding the performance since we need to go through the React Native bridge on every search.

Note that for now we only provide the offline experience for the enterprise customers with an additional cost. I don’t know on which plan you are but it’s an information to take into account.

Hope that helps, let me know if you have questions.

Hi @samuel.vaillant,

Thank you for taking the time to look into the offline capability. I have to discuss this with my client first. Anyhow, wanted to ask you regarding connectHighlight connector. I am confused on how/where to use it with connectInfiniteHits!

at the moment the component <Hits /> is using connectInfiniteHits and I got lost on how to include the highlight connector with it since the examples that I went through are mostly for widgets. Also, do I have to set the attributes to be highlighted at indexing time, e.g.

index.setSettings({
  attributesToHighlight: [
    'content',
    'description'
  ]
});

And one last thing, what if I want this to be general , and I mean the attributeName (in connectHightlight) referencing all the fields , without having to specify only one field in the hits/search result to be highlighted, because in the above code it seems that I can set as many fields I want when indexing, to look for matches to hightlight.

Hi @sherzad,

Did you see that we have a guide that explains how the highlighting works in the library?

By default all the searchable attributes of your index will be set as attributesToHighlight, so basically you don’t need to set them at indexing time. Unless you want to specify a particular attribute.

You can’t be general, because it’s not in the spirit of the connector. With that connector you create a component that will take an attribute that you want to highlight and then render this attribute. Let’s take a product as an example. We want to highlight the name and the description, so we will need render two components (one for each attribute).

const CustomHighlight = connectHighlight(
  ({ attributeName, hit, highlight }) => {
    const highlights = highlight({ 
      hit, 
      attributeName, 
      highlightProperty: "_highlightResult" 
    });

    rreturn (
      <Text>
        {highlights.map(({ value, isHighlighted }) =>
          isHighlighted ? (
            <Text style={{ fontStyle: "italic" }}>{value}</Text>
          ) : (
            value
          )
        )}
      </Text>
    );
  }
);

const CustomInfiniteHits = connectInfiniteHits(({ hits }) => (
  <View>
    {hits.map(hit => (
      <View>
        <CustomHighlight attributeName="name" hit={hit} />

        <CustomHighlight attributeName="description" hit={hit} />
      </View>
    ))}
  </View>
));