Reputation: 135
I have a React Native app built via Expo and I want add a search funstion to search a FlatList using a Search Bar in React Native. The search bar bellow is from React Native Paper.
This is my code (App.js):
constructor(props) {
super(props);
this.state = {
dataSource: []
}
}
state = {
firstQuery: '',
};
componentDidMount() {
const url = '// My URL'
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.product
})
})
.catch((error) => {
console.log(error)
})
}
state = {
search: '',
};
updateSearch = search => {
this.setState({ search });
};
SearchFilterFunction(text) {
const newData = this.dataSource.filter(function(item) {
const itemData = item.name ? item.name.toUpperCase() : ''.toUpperCase();
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({
dataSource: newData,
text: text,
});
}
render() {
const { search } = this.state;
const { firstQuery } = this.state;
return (
<Searchbar
placeholder="Search"
onChangeText={query => {text => this.SearchFilterFunction(text)}}
value={firstQuery} />
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem} />
);
}
}
Do I need to set more default state
? Is isLoading
or error: null
necessary?
What am I doing wrong?
UPDATE This is my App.js now:
constructor(props) {
super(props);
this.state = {
isLoading: true,
text: '',
dataSource: []
};
this.arrayholder = [];
}
state = {
firstQuery: '',
};
componentDidMount() {
const url = '// My URL'
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.product
}, {
function() {
this.arrayholder = responseJson;
}
}
)
})
.catch((error) => {
console.log(error)
})
}
state = {
search: '',
};
updateSearch = search => {
this.setState({ search });
};
SearchFilterFunction(text) {
const newData = this.dataSource.filter(function(item) {
const itemData = item.name ? item.name.toUpperCase() : ''.toUpperCase();
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({
dataSource: newData,
text: text,
});
}
renderItem = ({item}) => {
return (
// Code
);
}
render() {
return (
<Searchbar
placeholder="Search"
onChangeText={query => {text => this.SearchFilterFunction(text)}}
value={this.state.text} />
);
}
It's giving me a 'Invariant Violation: Invalid argument passed as callback. Expected a function. Instead received: [object Object]'
Upvotes: 4
Views: 2457
Reputation: 13906
When you search, you need a key to get it right. For example, if you search by address,
<Searchbar
placeholder="Search"
onChangeText={{text => this.SearchFilterFunction(text)}}
value={this.state.text} />
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
keyExtractor={item => item.address}
/>
Upvotes: 1
Reputation: 4961
You need to tell flatlist
that if something changes in ABC
state variable then look for data change in source and re-render. Without this, it won't use new values.
So, to tell that you need to pass one prop extraData
,
<FlatList
extraData={this.state.dataSource}
data={this.state.dataSource}
renderItem={this.renderItem} />
Now if anything changes in dataSource
, flatlist
will re-render its content
Upvotes: 1