Reputation:
I just wonder something about updating state in React. I'm working on basic "to-do app". I created a list & mapped for each element. The user can add a new element in the list and can change the status of the element.
Now, I want the state to update for every click. For example, when the user clicked the completed button, the state is called list will be contained only completed items. I can do it. But after I update the list, I can't access default list. For example, when the user click the button;
changeView(event) {
let clickStatus = event.target.value
if (clickStatus = 'completed') {
const newList = this.state.list.filter((item) => {
return item.completed
})
this.setState({
this.state.list: newList
})
}
But after this, I can't access the list that contains every item.
This is my code:
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
list: [
{
'text': 'First Item',
'completed': false
},
{
'text': 'Second Item',
'completed': false
},
{
'text': 'Third Item',
'completed': true
}
]
}
this.handleStatus = this.handleStatus.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(event) {
event.preventDefault()
const newItem = {
'text': this.refs.new.value,
'completed': false
}
this.setState({
list: this.state.list.concat([newItem])
})
this.refs.new.value = ''
}
handleStatus(event) {
const itemText = this.state.list[event.target.value].text
const itemStatus = this.state.list[event.target.value].completed
const newItem = {
'text': itemText,
'completed': itemStatus ? false : true
}
const list = this.state.list
list[event.target.value] = newItem
this.setState({
list
})
}
render() {
const Item = this.state.list.map((item, index) => {
return <li onClick={this.handleStatus} className={(item.completed) ? 'done' : 'default'} value={index} status={item.completed}>{item.text}</li>
})
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type='text' ref='new'></input>
<button type='submit'>Add</button>
</form>
<ul>
{Item}
</ul>
<div>
<button
value='all'
type='submit'>All
</button>
<button
value='completed'
type='submit'>Completed
</button>
<button
value='pending'
type='submit'>Pending
</button>
</div>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
Upvotes: 2
Views: 14150
Reputation: 6674
Instead of updating items list in state on each filter change use state property to decide which items should be displayed during rendering.
State should always store whole list and you should just set state property indicating that completed
filter is active:
changeView(event) {
let clickStatus = event.target.value
this.setState({
completedFilter: clickStatus === 'completed' ? true : false
})
}
and then use this property to filter displayed items in render method:
render() {
let fileredItems = this.state.list;
if (this.state.completedFilter) {
fileredItems = this.state.list.filter((item) => item.completed);
}
return (
...
{
filteredItems.map((item) => {
//return item node
})
}
);
}
Upvotes: 3