ReactiveSearch how to stop initial query on load - react-native

So I've got ReactiveSearch working fine but I've noticed on the initial load it performs a query to fetch items - given my index will have perhaps a million items in it I'd ideally like to turn this off and only return results from the autosuggest?
<ReactiveBase
app="tths-shop-items"
url="my-es-cluster"
credentials="user:password"
>
<ScrollView>
<View style={styles2.container}>
<DataSearch
componentId="searchbox"
dataField={[
'name'
]}
placeholder="Search"
/>
<ReactiveList
componentId="results"
dataField="name"
size={7}
showResultStats={true}
pagination={true}
react={{
and: "searchbox"
}}
onData={(res) => {
return (
<View style={styles2.result}>
<Image source={{ uri: res.image.replace('http', 'https') }} style={styles2.image} />
<View style={styles2.item}>
<Text style={styles2.title}>{res.name}</Text>
</View>
</View>
)}
}
/>
</View>
</ScrollView>
</ReactiveBase>
EDIT
I also tried adding the default value in order to try and stop the initial query returning data. But it doesn't seem to work as expected.
defaultValue="3245423 kjhkjhkj 2kj34h12jkh 213k4jh12"
EDIT 2:
I've also tried defaultQuery in the following format and added it to the reactiveList and dataSearch components this gives me an error which is undefined is not an object 'this.defaultQuery.sort' - if I add sort to both queries it makes no difference:
defaultQuery={() =>
{
query: {
match_none: {}
}
}
}

I know it's an old question, but I stumbled upon the same problem.
My solution looks a little bit different - with the onQueryChange prop.
onQueryChange={
function(prevQuery, nextQuery) {
if ('match_all' in nextQuery['query']) {
nextQuery['query'] = { match_none: {} }
}
}
}
This will disable the ResultList with all results showing and only show results after you've selected any filter or entered a search term.

So here's one answer, you store the value that you click via the searchbox in state and then fiddle with the defaultQuery from there. Note default query does match_none: {} if there's no search text.
It's a bit inefficient as you still do a query that returns nothing, but it works - I'll leave this question open to give any better answers time to come up.
<ScrollView>
<View style={styles.mainContainer}>
<DataSearch
componentId="searchbox"
dataField={[
'name'
]}
placeholder="Search"
queryFormat="and"
noInitialQuery={true}
onValueChange={(value) => {
if(value === ''){
this.setState({searchText: null})
}
}}
onValueSelected={(value, cause, source) => {
this.setState({searchText: value.value})
}
}
/>
<ReactiveList
componentId="results"
dataField="name"
size={7}
showResultStats={true}
pagination={true}
react={{
and: "searchbox"
}}
defaultQuery={()=> {
if(this.state.searchText !== null){
return {
query: {
match: {
name: this.state.searchText
}
}
}
} else {
return {
query: {
match_none: {}
}
}
}
}}
onData={(res) => {
return (
<View style={styles2.result}>
<Image source={{ uri: res.image.replace('http', 'https') }} style={styles2.image} />
<View style={styles2.item}>
<Text style={styles2.title}>{res.name}</Text>
</View>
</View>
)}
}
/>
</View>
</ScrollView>

The selected answer was very useful but I changed the defaultQuery to use the original query in the event a search term is present:
defaultQuery={()=> {
if(this.state.searchText !== null){
return {
}
} else {
return {
query: {
match_none: {}
}
}
}
}}

Related

I want my app to not show articles or give them low priority to those that have already been seen

I have a basic article app like inshorts i am storing all the articles in database which i fetch on the opening and display them in card format.Now I want to implement that when a card id viewed it should get low priority and render at the end next time the app is opened on that mobile.
I have no clue how to implement this.
This is how i am currently rendering it
renderArtciles=()=>{
let len=this.state.dataSource.length;
return this.state.dataSource.map((item,i)=>{
this.state.id=item._id;
this.state.priority=item.priority;
this.state.views=item.views;
if (i == this.state.currentIndex-1)
{
return(
<Animated.View key={item._id} {...this.state.panResponder.panHandlers} style={this.state.swiped_pan.getLayout()}>
< View style={{ flex: 1,position:'absolute',height:height,width:width,backgroundColor:'white'}}>
< View style={styles.Imagebody}>
<Image source={{ uri:item.img.data }} style={styles.image} />
</View>
<View style={styles.inner}>
<Text>{item.body} i==={i}{this.state.currentIndex} </Text>
</View>
</View>
</Animated.View>
)
}
else if (i < this.state.currentIndex)
{
return null
}
if (i == this.state.currentIndex)
{
return(
<Animated.View key={item._id} {...this.state.panResponder.panHandlers} style={this.state.pan.getLayout()}>
< View style={{ flex: 1,position:'absolute',height:height,width:width,backgroundColor:'white'}}>
< View style={styles.Imagebody}>
<Image source={{ uri:item.img.data }} style={styles.image} />
</View>
<View style={styles.inner}>
<Text>{item.body} i==={i}{this.state.currentIndex} </Text>
</View>
</View>
</Animated.View>
)
}
else{
return(
<Animated.View key={item._id} >
< View style={{ flex: 1,position:'absolute',height:height,width:width,backgroundColor:'white'}}>
< View style={styles.Imagebody}>
<Image source={{ uri:item.img.data }} style={styles.image} />
</View>
<View style={styles.inner}>
<Text>{item.body} i==={i}{this.state.currentIndex} </Text>
</View>
</View>
</Animated.View>
)
}
}
).reverse()
}
You could make use of AsyncStorage to store which items have been viewed (and how many times) in a JSON object which you can increment every time an item is viewed, and then retrieve again when the app is opened (and store in some state variable). You can then work out your ordering/priority logic based on the number of views.
To store the items you would do something like this:
_storeData = async () => {
try {
var itemsJson = {items: [
{item_id: 'foo', view_count: 10},
{item_id: 'bar', view_count: 5}
]}
await AsyncStorage.setItem('ItemViews', JSON.stringify(itemsJson));
} catch (error) {
// Error saving data
}
};
And to retrieve the items on app open you would do something like this:
_retrieveData = async () => {
try {
const items = await AsyncStorage.getItem('ItemViews');
// Rest of your code
} catch (error) {
// Error retrieving data
}
};

how to use if condition in .map function?

Hi, I used if condition like below, but there is nothing rendering on the screen. By the way, there is 'MAVI' in leader array
renderall() {
return this.state.leader.map(alb => {
if(alb.Renk == 'MAVI') {
<View style={styles.container} key={counter = counter + 1}>
<Text style={[styles.textStyle, {marginLeft:'5%'}]}> {alb.Tescil_No} </Text>
<Text style={[styles.textStyle, {marginLeft:'6%'}]}> {alb.GumrukAdi} </Text>
<Text style={[styles.textStyle, { marginLeft:'5%'}]}> {alb.ACIKLAMA} </Text>
</View>
}
});
}
You're missing a return in your .map. Notice that inside the if statement I am returning the items being mapped.
renderall() {
return this.state.leader.map(alb => {
if(alb.Renk == 'MAVI') {
return (
<View style={styles.container} key={counter = counter + 1}>
<Text style={[styles.textStyle, {marginLeft:'5%'}]}> {alb.Tescil_No} </Text>
<Text style={[styles.textStyle, {marginLeft:'6%'}]}> {alb.GumrukAdi} </Text>
<Text style={[styles.textStyle, { marginLeft:'5%'}]}> {alb.ACIKLAMA} </Text>
</View>
);
}
});
}
This article explains in more detail how the .map function works
https://codeburst.io/learn-understand-javascripts-map-function-ffc059264783
Here is a very small example showing how to use the .map function. Notice the return statement.
let leaders = ['Tom','Jerry','Mike'];
let mappedLeaders = leaders.map((leader, index) => {
return `${leader} is number ${index}`; // notice that I am returning here
})
console.log(mappedLeaders)
Here is an example of using a .map with an if statement inside it. Notice we will get undefined for the first item in the mappedLeaders as we are not returning anything for the first item because Tom is excluded due to the fact that his name is too short.
let leaders = ['Tom','Jerry','Mike'];
let mappedLeaders = leaders.map((leader, index) => {
if (leader.length > 3) {
return `${leader} is number ${index}`; // notice that I am returning here
}
});
console.log(mappedLeaders)

Rendering results of filter with react native

I've this....
renderSearchResults() {
if (!this.props.events.successfully) {
return
}
//This don't work
/*
return (
<View>
{
this.props.events.data.data.filter(flt =>
flt.location.toLowerCase().includes(this.state.searchText.toLowerCase()))
.map(item => {
alert(item)
return (<View style={style.searchResultsWrapper} key={'ev' + item.id}>
<EventItem data={item}></EventItem>
</View>)
})
}
</View>
)
*/
//This Works
return (
<View>
{
this.props.events.data.data.map(item => {
return (
<View style={style.searchResultsWrapper} key={'ev' + item.id}>
<EventItem data={item}></EventItem>
</View>
)
})
}
</View>
)
}
I need to make the non-working code to work. Actually the alert line executes fine, so it means that's iterating fine. However this can't render results. Any clue ?
I just put the working code to demonstrante that this works ok without the filter. Is there something that I did't get it ?
Actually, your code run properly with some change like in the below in my demo code. Maybe you look your all component and try with a component like in the below.
<View>
{
this.props.events.data.data.filter(flt =>
flt.location.toLowerCase().includes(this.state.searchText.toLowerCase()))
.map(item => {
alert(item)
return (<View key={'ev' + item.id}>
<Text>{item.location}</Text>
</View>)
})
}
</View>

Why set dollar is not working?

If i just set require('../img/dest.png') the image is working, but when i try to use like
It will show error
calls to require expect exactly 1 string literal argument but this was found: require(""+item.img+"").(null)
Any one knows what happens in my dollar variable ?
Thanks in advance.
render() {
// Taken from https://flatuicolors.com/
const items = [
{ name: 'Name', code: '#1abc9c', url: 'yahoo.com.tw', img: '../img/dest.png' }
];
return (
<GridView
itemDimension={130}
items={items}
style={styles.gridView}
renderItem={item => {
console.log(`'${item.img}'`);
return (
<TouchableOpacity onPress={() => this.showLinkAlert(item.name, item.url)}>
<ImageBackground source={require(`'${item.img}'`)} style={[styles.itemContainer, { backgroundColor: '#bdc3c7' }]}>
<Text style={styles.itemName}>{item.name}</Text>
</ImageBackground>
</TouchableOpacity>
);
}}
/>
);
}
}
The string substitution happens at run time, but require happens at build time. So when require runs it doesn't substitute anything, it just tries to find a file called that.

if statement in render method - react native

i would like to use if statement in the return of render method , what i mean is something like this :
export default class App extends Component
{
render()
{
return(
<View>
if(this.state.error)
{
<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>
}
else
{
<View>
<List dataArray={this.state.items}></List>
</View>
}
</View>
);
}
}
i can use ternary operator , but what i want is to use if statement if it possible
Background
What is the difference between a statement and expression
Specific to JavaScript:
What is the difference between an expression and a statement in JS?
JavaScript: declarations vs expressions vs statements
return expects an expression as the argument. if statements are not expressions (makes sense, since statement is in the name).
The implementation details of JSX (that stuff with <Tags>, but in javascript) is also relevant. JSX is compiled into normal JavaScript.
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
compiles to
React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
documentation.
If you want to evaluate a JavaScript expression in JSX you need to enclose it in curly braces.
const myButtonColor = 'blue'
//...
<MyButton color={myButtonColor} shadowSize={2}>
Click Me
</MyButton>
Back to the Question
Ways of accomplishing if-like functionality:
inline logical and (&&)
ternary operator (?)
return in if/else statements
Let's look at some examples:
Inline Logical And
render() {
return (
<View>
{this.state.error && <Text> There's an error! </Text>}
</View>
)
}
This method is the simplest and I recommend trying it first. It makes sense when you don't want to do anything if the condition evaluates to false. && behaves a bit different in javascript than in other languages. When this.state.error evaluates to false, render returns this.state.error, which may have unintended consequences if this.state.error happens to be the empty string or 0.
Ternary Operator
render() {
return (
<View>
{this.state.error ? <Text>Error!</Text> : <Text>No Error!</Text>}
</View>
)
}
The biggest problem with this is that the lines get long pretty quickly. You can get around this with parentheses.
render() {
return (
<View>
{this.state.error ? (
<Text>Long, detailed error message</Text>
) : (
<Text>No Error!</Text>
)}
</View>
)
}
You could alternatively use JavaScript strings declared before return along with this method.
Return in if Block
render() {
if(this.state.error) {
return (<Text>Long, detailed error message</Text>)
}
else {
return (<Text>No Error!</Text>)
}
}
The problem with this method is if that if you have a long render method and a small conditional change, you will have to nearly repeat the render function in each if block. I generally use this method as a last resort.
this is the simple one :
render()
{
return(
<View>
{this.state.error ?
(<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>)
:
(<View>
<List dataArray={this.state.items}></List>
</View>)
}
</View>
);
}
maybe can help you :)
You should try somthing like this:
export default class App extends Component {
render() {
if(this.state.error)
{
return (
<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>
)
}
else {
return (
<View>
<List dataArray={this.state.items}></List>
</View>
);
}
}
}
You can do this:
render()
{
return(
<View>
{this.state.error &&
<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>
}
{!this.state.error &&
<View>
<List dataArray={this.state.items}></List>
</View>
}
</View>
);
}
I suggest to take advantage of js in this case:
{ this.state.error &&
<View>
<Text>show error</Text>
</View>
}
{ !this.state.error &&
<View>
<Text>all good</Text>
</View>
}
It can look better than ternary in some cases.