Reputation: 133
I am trying to develop a very simple dashboard with some information. I'm trying to add in a search filter into my code so that I can narrow my data by names. In many other tutorials, I found that they have common used name.toLowerCase().indexOf(this.state.filterName.toLowerCase()) >= 0
but I just didn't work for me and would like to seek guidance from you guys.
You may also provide feedback on the general structure of my code!
Tables.js
class Table extends Component {
constructor(props){
super(props);
this.state = {
filterName: this.props.filterName,
toShow: 'all',
myArrays: [
{ 'id': 1, 'name': 'Eric', 'email': '[email protected]', 'role': 'student', 'isadmin': 'false' },
{ 'id': 2, 'name': 'Amanda', 'email': '[email protected]', 'role': 'student', 'isadmin': 'false' },
{ 'id': 3, 'name': 'Brenda', 'email': '[email protected]', 'role': 'staff', 'isadmin': 'true' },
{ 'id': 4, 'name': 'Charles', 'email': '[email protected]', 'role': 'teacher', 'isadmin': 'true' },
{ 'id': 5, 'name': 'Daimon', 'email': '[email protected]', 'role': 'assistant', 'isadmin': 'false' }
]
};
this.toShowAdmin = this.toShowAdmin.bind(this);
}
toShowAdmin(){
if (this.state.toShow === 'all'){
this.setState({ toShow: 'admin' }, () => console.log(this.state.toShow ))
} else {
this.setState({ toShow: 'all' }, () => console.log(this.state.toShow ))
}
}
render(){
let myArrays = []
if (this.state.toShow === 'all'){
myArrays = this.state.myArrays;
} else if (this.state.toShow === 'admin'){
myArrays = this.state.myArrays.filter(row => row.isadmin === 'true')
}
myArrays = this.state.myArrays.filter(row => {
return row.name.toLowerCase().indexOf(this.state.filterName.toLowerCase()) >= 0;
});
return(
<div>
<table className="table">
<thead className="thead-dark">
<tr>
<th scope="col"> name </th>
<th scope="col"> email </th>
<th scope="col"> role </th>
<th scope="col"> isadmin </th>
</tr>
</thead>
<tbody>
{myArrays.map(row=>
<tr key={row.id}>
<td> {row.name} </td>
<td> {row.email} </td>
<td> {row.role} </td>
<td> {row.isadmin} </td>
</tr>
)}
</tbody>
</table>
<button type='button' className='btn btn-primary' onClick={this.toShowAdmin}> Admins </button>
{ this.state.filterName }
</div>
);
}
}
export default Table;
Main.js
class Main extends Component {
constructor(props){
super(props);
this.state = {
filterName: ''
};
this.filterUpdate = this.filterUpdate.bind(this);
}
filterUpdate(value){
this.setState({ filterName: value}, () => console.log(this.state.filterName))
}
render(){
return(
<div>
<Search
filterName={this.state.filterName}
filterUpdate={this.filterUpdate}/>
<Tables
filterName={this.state.filterName}/>
</div>
);
}
}
export default Main;
Upvotes: 0
Views: 67
Reputation: 467
You have to use componentWillReceiveProps
to update your child state with parent props once the child component has been loaded. Add something like this to child component -
componentWillReceiveProps(){
this.setState({filterName: this.props.filterName})
}
See this Stack Over Flow Answer
Otherwise, if your logic allows you to use the prop directly in render, you may also do -
myArrays = this.state.myArrays.filter(row => {
return row.name.toLowerCase().indexOf(this.props.filterName.toLowerCase()) >= 0;
});
edit - use componentDidUpdate()
As rightly pointed out in comments, componentWillReceiveProps()
is deprecated. Use componentDidUpdate()
instead.
componentDidUpdate(){
this.setState({filterName: this.props.filterName})
}
Upvotes: 1
Reputation: 6582
You should use this.props.filterName
directly like this:
myArrays = this.state.myArrays.filter(row => {
return row.name.toLowerCase().indexOf(this.props.filterName.toLowerCase()) >= 0;
});
Upvotes: 0