Reputation:
I am trying to filter a list using react, but surprisingly, for such a common task, cannot find anything online to help me achieve this.
I have an array of users which I then want to filter through (starting off with name - I can work out filtering by age then). The array is in my redux store and looks like the below.
let users = [
{
name: 'Raul',
age: 29
},
{
name: 'Mario',
age: 22
}
];
My entire component looks like the below.
class Test extends Component {
constructor(props) {
super(props);
this.state = {
users: this.props.users
};
this.filterList = this.filterList.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
users: nextProps.users
});
}
filterList(event) {
let users = this.state.users;
users = users.filter(function(user){
//unsure what to do here
});
this.setState({users: users});
}
render(){
const userList = this.state.users.map((user) => {
return <li>{user.name} {user.age}</li>;
});
return(
<input type="text" placeholder="Search" onChange={this.filterList}/>
<ul>
{ userList }
</ul>
);
}
}
Upvotes: 2
Views: 15664
Reputation: 191
It always worked well for me that way.
const [data, setData] = useState([{name: 'Kondo'}, {name: 'Gintoki'}])
const handleFilterFilesTable = () => {
return data
.filter((element) => {
if (searchText !== "") {
return element?.name?.toLowerCase()?.includes(searchText?.toLowerCase())
}
return element
})
}
// ...
return (
//...
<Table data={handleFilterFilesTable()} />
)
That way I can apply multiple filters working together simply by extending the filter method like this
// ...
return data.filter().filter().filter()//...
// ...
Upvotes: 0
Reputation: 21
let datas =[
{
"id":1,
"title":"Ucat",
"handle":"mi"
},
{
"id":2,
"title":"Acat",
"handle":"csk"
},
{
"id":3,
"title":"Vcat",
"handle":"kkr"
},
{
"id":4,
"title":"Atar",
"handle":"pkbs"
}];
const [search, setSearch] =useState(datas);
const handleInputChange = (e) => {
var dm = e.target.value;
var str =dm.toString();
var debug = datas.filter(x=> x["title"].toLowerCase().includes(str));
setSearch(debug);};
<input type="text" onChange={handleInputChange}/>
{search.map((item)=>(
<div key={item.id}>
<ul>
<li>
{item.handle}
<br/>
{item.title}
</li>
</ul>
</div>
))};
Upvotes: 1
Reputation: 18546
If you want to filter for name
you can use .filter
together with .startsWith
or .indexOf
to return true or false for a given user.
You've also set a new list of users on the onChange event, which results in an empty array sooner or later. Here I've used the user
state that is only changed by the props, and a filteredUsers
that is changed when a keystroke happened.
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
users: this.props.users,
filteredUsers: this.props.users,
q: ''
};
this.filterList = this.filterList.bind(this);
this.onChange = this.onChange.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState(
{
users: nextProps.users,
filteredUsers: nextProps.users
},
() => this.filterList()
);
}
onChange(event) {
const q = event.target.value.toLowerCase();
this.setState({ q }, () => this.filterList());
}
filterList() {
let users = this.state.users;
let q = this.state.q;
users = users.filter(function(user) {
return user.name.toLowerCase().indexOf(q) != -1; // returns true or false
});
this.setState({ filteredUsers: users });
}
render() {
const userList = this.state.filteredUsers.map(user => {
return <li>{user.name} {user.age}</li>;
});
return (
<div>
<input
type="text"
placeholder="Search"
value={this.state.q}
onChange={this.onChange}
/>
<ul>
{userList}
</ul>
</div>
);
}
}
const userList = [
{
name: 'Raul',
age: 29
},
{
name: 'Mario',
age: 22
}
];
ReactDOM.render(<Test users={userList} />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Upvotes: 5
Reputation: 104359
You need one more state
variable to store the search result, initialise that variable by same data, once user type anything store the filtered data in that, Try this:
let users = [
{
name: 'Raul',
age: 29
},
{
name: 'Mario',
age: 22
}
];
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
users: users,
result: users,
};
this.filterList = this.filterList.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
users: nextProps.users,
});
}
filterList(event) {
let value = event.target.value;
let users = this.state.users, result=[];
result = users.filter((user)=>{
return user.name.toLowerCase().search(value) != -1;
});
this.setState({result});
}
render(){
const userList = this.state.result.map((user) => {
return <li>{user.name} {user.age}</li>;
});
return(<div>
<input type="text" placeholder="Search" onChange={this.filterList}/>
<ul>
{userList}
</ul>
</div>
);
}
}
ReactDOM.render(<Test/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
Upvotes: 1
Reputation: 56
If you want to filter the list, you must have a criteria to filter against. For instance you have a variable let filterAge = 18;
In that case you can filter the userlist against that value using
let users = users.filter(function(user){
//return all users older or equal to filterAge
return user.age >= filterAge;
});
Every result from the function that equals true, will be added to the users
variable. A false return will leave it out. How you determine true / false is up to you. Hardcode it (not very useful), a simple equals statement (as above) or a function doing higher math. Your choice.
Upvotes: 0