var uuid = require('node-uuid');
import React, { Component } from 'react';
import './App.css';
import TodoList from './components/Todolist';
import AddTodo from './components/AddTodo';
import SearchTodo from './components/SearchTodo';
class App extends Component {
constructor(props){
super(props);
this.state = {
todos:[{
id:uuid(),
text: 'learn React',
completed:false
},
{
id:uuid(),
text: 'Cut your hair',
completed:false
},
{
id: uuid(),
text: 'go to church',
completed: true
}],
searchVal: '',
showCompleted: false
}
this.handleAddTodo = this.handleAddTodo.bind(this)
this.handleSearch = this.handleSearch.bind(this)
this.toggleTodo = this.toggleTodo.bind(this)
this.filterTodos = this.filterTodos.bind(this)
}
handleAddTodo(inputValue){
this.setState({
todos:[
...this.state.todos,
{
id: uuid(),
text: inputValue,
completed: false
}
]
})
}
toggleTodo(id){
var updatedTodo = this.state.todos.map((todo) => {
if(todo.id === id){
todo.completed = !todo.completed;
}
return todo
});
console.log(updatedTodo.completed)
this.setState({
todos: updatedTodo,
})
}
handleSearch(searchVal, showCompleted){
this.setState({
searchVal: searchVal.toLowerCase(),
showCompleted: showCompleted
})
}
// Error here
filterTodos(todos, showCompleted, searchVal){
var filteredTodos = this.state.todos;
filteredTodos = filteredTodos.filter((todo) => {
var text = todo.text.toLowerCase();
return this.state.searchVal.length === 0 || todo.indexOF(searchVal) > -1
})
this.setState({
todos: filteredTodos
})
}
render() {
return (
<div>
<SearchTodo onSearch={this.handleSearch}/>
<TodoList todos={this.state.todos} onToggle={this.toggleTodo} filterTodos={this.filterTodos}/>
<AddTodo handleAdd={this.handleAddTodo}/>
</div>
);
}
}
export default App;
我正在尝试一个todo列表应用程序。当我尝试编写一个方法来过滤我创建的列表时,我遇到了上面提到的错误,我想知道我做错了什么。
否则,有什么更好的方法呢?
答案 0 :(得分:0)
你的问题列在这一行:
var filteredTodos = this.state.todos;
由于this.state.todos
是一个数组,因此您要为filteredTodos
分配相同的引用。
这将使状态在下一个代码块中变异,无意中导致React安排更新。您的代码相当于:
this.state.todos = filteredTodos.filter((todo) => {
var text = todo.text.toLowerCase();
return this.state.searchVal.length === 0 || todo.indexOF(searchVal) > -1
})
因此,当您在下一行设置State时,由于损坏的更新正在进行,因此React会对您发出警告。
this.setState({
todos: filteredTodos
})
要解决此问题,您应该在过滤之前创建状态的浅表副本。请记住从不改变组件中的状态,应始终将其视为只读值和不可变。在处理数组和对象时创建副本。 Arrays本身的Filter方法总是返回一个新数组:
filterTodos(todos, showCompleted, searchVal){
var filteredTodos = this.state.todos.filter((todo) => {
var text = todo.text.toLowerCase();
return this.state.searchVal.length === 0 || todo.indexOf(searchVal) > -1
})
this.setState({
todos: filteredTodos
})
}