Hello, I'm using react-native.
From the tutorial (https://community.algolia.com/react-instantsearch/Getting_started_React_native.html), I can connect algolia and display all the data on my ListView. Also, I can do the search with the search box. Great.
However, how to 'hide' the 'Hits' (all the data) at the beginning? For example, I have 50 user data, and I want a search box + Empty ListView (blank) UI. Then when the user begins to type words in the search box, the result is going to be displayed on the ListView(real time).
I followed the tutorial exactly, so what I used is like :
const SearchBox = connectSearchBox(({ refine, currentRefinement }) => {
const styles = {
height: 60,
borderWidth: 1,
padding: 10,
margin: 10,
flex: 1,
};
return (
<TextInput
style={styles}
onChangeText={text => refine(text)}
value={currentRefinement}
placeholder={'Search a product...'}
clearButtonMode={'always'}
spellCheck={false}
autoCorrect={false}
autoCapitalize={'none'}
/>
);
});
const Hits = connectInfiniteHits(({ hits, hasMore, refine }) => {
/* if there are still results, you can
call the refine function to load more */
const onEndReached = function() {
if (hasMore) {
refine();
}
};
return (
<FlatList
data={hits}
onEndReached={onEndReached}
keyExtractor={(item, index) => item.objectID}
renderItem={({ item }) => {
return (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Image
style={{ height: 100, width: 100 }}
source={{ uri: item.image }}
/>
<View style={{ flex: 1 }}>
<Text>
{item.name}
</Text>
<Text>
{item.type}
</Text>
</View>
</View>
);
}}
/>
);
});
return(
<View style={styles.container}>
<InstantSearch
appId="latency"
apiKey="6be0576ff61c053d5f9a3225e2a90f76"
indexName="contacts"
>
<View
style={{
flexDirection: 'row',
}}
>
<SearchBox />
</View>
<Hits />
</InstantSearch>
</View>
)
Also, I'm going to use Index to do the search with different indices. For example, if I search 'Alex', the result can be filtered by some buttons. If I click 'Account', only data from 'contacts' index will be displayed. If I click 'Posts', only post like 'Alex likes Apple' from 'post' index will be displayed.
I tried several ways but still can't find a good solution. Thanks for any help!
Currently if you don't want to display the hits of the empty query you'll need to use conditional display. I detailed this and give a live code sample in this discourse thread: https://discourse.algolia.com/t/need-guidance-explicit-example-on-how-to-incorporate-createconnector/2041/3
Like I said at the end of this thread we're currently thinking of two improvements about this subject:
You can follow this github issue about the conditional display new API proposal. If you have any feedback about it please feel free to give them :)
Also, could you detailed what is not working using Index and what approach did you try?
@mthuret Thank you so much for your help. I will take a look your code sample and give you the feedback whether it works (Hopefully it works!).
For the Index, in the documentation (https://community.algolia.com/react-instantsearch/guide/Multi_index.html), this is about how we use it in ReactJS. I feel the docs about react native is still very limited (though they are pretty similar!).
The code example is :
<InstantSearch
appId="latency"
apiKey="6be0576ff61c053d5f9a3225e2a90f76"
indexName="bestbuy"
>
<SearchBox />
<p>Results in first dataset</p>
<Hits />
<Index indexName="ikea">
<p>Results in second dataset</p>
<Hits />
</Index>
</InstantSearch>
Firstly, in RN, we can't import Index from /dom
import { InstantSearch, Hits, SearchBox, Index } from 'react-instantsearch/dom';
I tried import { ... Index } from 'react-instantsearch/native'; Is this correct?
Secondly, is the sample exactly same in RN way? I tried it once before, but it doesn't work. So if it's exactly in the same way, I will try it again. Thank you!
Yes, you can import Index from native.
You're right we improved a bit the documentation for react-native publishing a getting started but we have still things to do :)
It should be usable in the same way than for a normal React app. If it does'nt then I'll investigate :)
@mthuret Okay, I will try to solve these two problems and let you know the results. Thanks for the quick reply! :)
@mthuret The conditional display using createConnector works. However, the Index doesn't work. I tried 2 ways but no one works (No results return).
const MyHits = createConnector({
displayName: 'ConditionalQuery',
getProvidedProps(props, searchState, searchResults) {
const { query, hits } = searchResults.results ? searchResults.results : {};
return { query, hits };
}
})(({ query, hits }) => {
const hs =
hits && query
? hits.map(hit =>
<View>
<Text>{hit.username}</Text>
</View>
)
: null;
return (
<View>
{hs}
</View>
);
});
<InstantSearch
appId='myappid'
apiKey='myapikey'
indexName="posts"
>
<SearchBox/>
<MyHits />
<Index indexName="contacts">
<MyHits />
</Index>
</InstantSearch>
<InstantSearch
appId='myappid'
apiKey='myapikey'
indexName="posts"
>
<SearchBox/>
<Index indexName="posts">
<MyHits />
</Index>
<Index indexName="contacts">
<MyHits />
</Index>
</InstantSearch>
If I don't use Index tag, either one ('posts' or 'contacts') works (using MyHits directly).
Do you have any error? What is the behaviour?
I tried this and it was working:
import { InstantSearch, Index, Configure } from 'react-instantsearch/native';
<View style={styles.container}>
<InstantSearch
appId=""
apiKey=""
indexName="ikea"
searchState={this.state.searchState}
onSearchStateChange={this.onSearchStateChange}
>
<ConnectedSearchBox />
<Configure hitsPerPage={3} />
<Index indexName="ikea">
<ConnectedHits />
</Index>
<Index indexName="airbnb">
<ConnectedHits />
</Index>
</InstantSearch>
</View>
It works! Thanks!
However, I can't use createConnector with multiple Indices, can you please test it?
All other cases :
Hits with no Index, Hits with single Index, Hits with multiple Indices, createConnector with no Index, createConnector with single Index, works.
My code :
const Hits = createConnector({
displayName: 'ConditionalQuery',
getProvidedProps(props, searchState, searchResults) {
const { query, hits } = searchResults.results ? searchResults.results : {};
return { query, hits };
}
})(({ query, hits }) => {
const hs =
hits && query
?
hits.map(hit =>
<View style={{marginBottom: 20}}>
<Text>{hit.username}</Text>
<Text>{hit.age}</Text>
</View>
)
: null;
return (
<View>
{hs}
</View>
);
});
<InstantSearch
appId=" id "
apiKey=" key "
indexName="indexA"
searchState={this.state.searchState}
onSearchStateChange={this.onSearchStateChange}
>
<SearchBox/>
<Index indexName="indexA">
<Hits />
</Index>
<Index indexName="indexB">
<Hits />
</Index>
</InstantSearch>
The problem is that no search result return while I'm typing words in the Searchbox.
Also, is it possible to separate Searchbox and the Hits? I understand that all the components should be wrapped in InstantSearch. I tried this :
<InstantSearch
appId="id"
apiKey="key"
indexName="indexA"
searchState={this.state.searchState}
onSearchStateChange={this.onSearchStateChange}
>
<SearchBox/>
</InstantSearch>
```jsx
apiKey=" key "
indexName="indexA"
searchState={this.state.searchState}
onSearchStateChange={this.onSearchStateChange}
>
// single hits here. I need multiple indices, but just use single index here
`````
For some reason, I can't put all the Hits with the Searchbox in one InstantSearch, and I only need one Searchbox. My solution doesn't work. It's like 1 Searchbox control multiple Hits (createConnector, different indices) which embedded in the parent View. Thanks.
Hi @MelodiiLy, I'm sorry I didn't see your answer.
Implementing a complete widget compatible with multi indices using the createConnector is not easy. You need to have a lot of knowledge of the internal of react instantsearch.
If you need to access hits, query and the refine function you should use our connectAutoComplete connector. If that's not enough can you explicit your use case?
I'm not sure to fully get your last question, could you illustrate it using codesandebox and for example this template: https://codesandbox.io/embed/github/algolia/react-instantsearch/tree/master/packages/react-instantsearch/examples/multi-index
Thanks a lot!
I'm closing this. Do not hesitate to reopen it if you still have issues.
Most helpful comment
Currently if you don't want to display the hits of the empty query you'll need to use conditional display. I detailed this and give a live code sample in this discourse thread: https://discourse.algolia.com/t/need-guidance-explicit-example-on-how-to-incorporate-createconnector/2041/3
Like I said at the end of this thread we're currently thinking of two improvements about this subject:
You can follow this github issue about the conditional display new API proposal. If you have any feedback about it please feel free to give them :)
Also, could you detailed what is not working using
Indexand what approach did you try?