Reputation: 15700
in my filter() callback newList contains the correct array but state is not being updated.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>list</title>
<script src="react/react.js"></script>
<script src="react/react-dom.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id='container'>
</div>
</body>
</html>
<script type = 'text/jsx'>
class FilteredList extends React.Component{
constructor(props){
super(props);
this.state={list:this.props.list};
}
filter(input){
var newList = this.state.list.filter(function(item){
return (item.search(input.target.value)!=-1);
});
console.log(newList);
this.setState({list:newList});
console.log(this.state.list);
}
render(){
return(
<div>
<input type='text' placeholder='Filter' onChange={this.filter.bind(this)} />
<List items={this.state.list} />
</div>
);
}
}
class List extends React.Component{
constructor(props){
super(props);
this.state={items:this.props.items};
}
render(){
return(
<ul>
{this.state.items.map(function(item){
return(<li key={item}>{item}</li>);
})}
</ul>
);
}
}
ReactDOM.render(
<div><FilteredList list={['anteater','bear','cat','dog','elephant','fox']} /></div>,
document.getElementById('container')
);
</script>
Upvotes: 0
Views: 126
Reputation: 16
For the state to be updated and the filtered result to display you need to re-render the child components on parent state change.
https://codepen.io/asifamingov/pen/QWwNOgQ
class List extends React.Component{
constructor(props){
super(props);
this.state={items:this.props.items};
}
componentWillReceiveProps({items}) {
this.setState({items:items});
}
render(){
return(
<ul>
{this.state.items.map(function(item){
return(<li key={item}>{item}</li>);
})}
</ul>
);
}
}
And one more issue I found is that you are mutating your original state
class FilteredList extends React.Component{
constructor(props){
super(props);
this.state={list:this.props.list, updatedList: this.props.list};
}
filter(input){
var updatedList = [...this.state.list];
var newList = updatedList.filter(function(item){
return item.toLowerCase().search(
input.target.value.toLowerCase()) !== -1;
});
this.setState({updatedList:newList});
}
render(){
return(
<div>
<input type='text' placeholder='Filter' onChange={this.filter.bind(this)} />
<List items={this.state.updatedList} />
</div>
);
}
}
Upvotes: 0
Reputation: 2852
This is because setState
is asynchronous. This means that the state is not immediately updated when the line is executed, but some moment later.
To execute code once the state has been updated, setState
takes a callback as second argument :
this.setState({list:newList}, () => console.log(this.state.list))
Upvotes: 3