Reputation: 1034
I'm trying to build a listView with a search bar, but it seems that the input value of the search bar doesn't get inserted and tested against available results.
Instead it return an empty text: [ ]
.
I've even made an empty array { id: 5, text: " ", text2: "test" }
and this also doesn't return any results..
I'm now wondering why does my search bar return empty?
The value of the input this.state.searchText
does get checked in the for loop
against any results.
for (i = 0; i < textLength; i++) {
if (aText[i].text === searchText) {
console.log("found: " + aText[i].text);
return aText[i];
}
}
I'm still learning, have I approached this wrong? Should I have used an object instead of an array?
And how come I don't get any results?
I've made an example app so you can see the code in an working environment.
Any kind of advice, feedback or criticism is more than welcome.
full example code
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import {
AppRegistry,
ListView,
View,
Text,
StyleSheet,
TextInput
} from "react-native";
// Row data (hard-coded)
const rows = [
{ id: 0, text: "View" },
{ id: 1, text: "Text" },
{ id: 2, text: "Image" },
{ id: 3, text: "ScrollView" },
{ id: 4, text: "ListView" },
{ id: 5, text: " ", text2: "test" }
];
// Row comparison function
const rowHasChanged = (r1, r2) => r1.id !== r2.id;
// DataSource template object
const ds = new ListView.DataSource({ rowHasChanged });
export default class App extends Component {
state = {
dataSource: ds.cloneWithRows(rows),
rows
};
setSearchText(event) {
const searchText = event.nativeEvent.text;
const textLength = this.state.rows.length;
const aText = this.state.rows;
const filteredTexts = this.state.rows.filter(checkText);
console.log("text: " + JSON.stringify(filteredTexts));
function checkText() {
var i;
for (i = 0; i < textLength; i++) {
if (aText[i].text === searchText) {
console.log("found: " + aText[i].text);
return aText[i];
}
}
}
this.setState({
searchText,
dataSource: this.state.dataSource.cloneWithRows(filteredTexts)
});
}
renderRow = rowData => {
return (
<Text style={styles.row}>
{rowData.text}
{rowData.text2}
</Text>
);
};
render() {
return (
<View style={styles.SearchBarContainer}>
<TextInput
placeholder="Search"
value={this.state.searchText}
onChange={this.setSearchText.bind(this)}
style={styles.searchBar}
underlineColorAndroid="#DD016B"
selectionColor="#DD016B"
/>
<ListView
style={styles.container}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
row: {
padding: 15,
marginBottom: 5,
backgroundColor: "skyblue"
}
});
AppRegistry.registerComponent("App", () => App);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Upvotes: 1
Views: 152
Reputation: 3856
I've suggest to use FlatList since ListView is depricated. I've rewrite your code a bit and you can check it on Expo Snack or just look into code below
import React, { Component } from "react";
import {
AppRegistry,
ListView,
View,
Text,
StyleSheet,
TextInput,
FlatList
} from "react-native";
// Row data (hard-coded)
const rows = [
{ id: 0, text: "View" },
{ id: 1, text: "Text" },
{ id: 2, text: "Image" },
{ id: 3, text: "ScrollView" },
{ id: 4, text: "ListView" },
{ id: 5, text: " ", text2: "test" }
];
export default class App extends Component {
state = {
rows,
filteredRows: rows,
};
setSearchText(event) {
const searchText = event.nativeEvent.text;
const textLength = this.state.rows.length;
const filteredTexts = this.state.rows.filter(row => {
return row.text.indexOf(searchText) !== -1;
});
console.log("text: " + JSON.stringify(filteredTexts));
this.setState({
searchText,
filteredRows: filteredTexts
});
}
renderRow = rowData => {
return (
<Text style={styles.row}>
{rowData.item.text}
{rowData.item.text2}
</Text>
);
};
render() {
return (
<View style={styles.SearchBarContainer}>
<TextInput
placeholder="Search"
value={this.state.searchText}
onChange={this.setSearchText.bind(this)}
style={styles.searchBar}
underlineColorAndroid="#DD016B"
selectionColor="#DD016B"
/>
<FlatList
style={styles.container}
data={this.state.filteredRows}
renderItem={this.renderRow}
/>
</View>
);
}
}
const styles = StyleSheet.create({
SearchBarContainer: {
marginTop: 40,
flex: 1
},
row: {
padding: 15,
marginBottom: 5,
backgroundColor: "skyblue",
color: 'black',
},
});
Upvotes: 1
Reputation: 363
This is very simple you don't need to use for loop to search from the array.
You can get your desired result by simply filter by text match in the object.
I have fixed your example app you can test it.
just replace your looped function with this line const filteredTexts = this.state.rows.filter(record => record.text.toLowerCase().match(searchText));
Upvotes: 2
Reputation: 980
You don't seem to have a state to hold the searchText
state = {
dataSource: ds.cloneWithRows(rows),
rows,
searchText:"" //ADD THIS
};
Upvotes: 2