我有一个简单易用的应用程序,除了能够从列表中删除项目外,工作正常。我已经为每个列表项添加了按钮。我知道我想使用.filter()方法向状态传递一个没有删除待办事项的新数组,但我不知道如何做这样的事情。
这是App的主要组成部分:
class App extends Component {
constructor(props){
super(props);
this.state = {
todos: [
{ description: 'Walk the cat', isCompleted: true },
{ description: 'Throw the dishes away', isCompleted: false },
{ description: 'Buy new dishes', isCompleted: false }
],
newTodoDescription: ''
};
}
deleteTodo(e) {
this.setState({ })
}
handleChange(e) {
this.setState({ newTodoDescription: e.target.value })
}
handleSubmit(e) {
e.preventDefault();
if (!this.state.newTodoDescription) { return }
const newTodo = { description: this.state.newTodoDescription,
isCompleted: false };
this.setState({ todos: [...this.state.todos, newTodo],
newTodoDescription: '' });
}
toggleComplete(index) {
const todos = this.state.todos.slice();
const todo = todos[index];
todo.isCompleted = todo.isCompleted ? false : true;
this.setState({ todos: todos });
}
render() {
return (
<div className="App">
<ul>
{ this.state.todos.map( (todo, index) =>
<ToDo key={ index } description={ todo.description }
isCompleted={ todo.isCompleted } toggleComplete={ () =>
this.toggleComplete(index) } />
)}
</ul>
<form onSubmit={ (e) => this.handleSubmit(e) }>
<input type="text" value={ this.state.newTodoDescription }
onChange={ (e) => this.handleChange(e) } />
<input type="submit" />
</form>
</div>
);
}
}
然后这是To-Do的组件:
class ToDo extends Component {
render() {
return (
<li>
<input type="checkbox" checked={ this.props.isCompleted }
onChange={ this.props.toggleComplete } />
<button>Destroy!</button>
<span>{ this.props.description }</span>
</li>
);
}
}
答案 0 :(得分:1)
在进一步说明之前,不要使用列表索引作为React Elements的键。给你的ToDo一个id并用它作为关键。有时你可以逃避这一点,但是当你删除它时,它几乎总会引起问题。
https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
如果您不想阅读该文章,请了解此
让我解释一下,关键是React用来识别DOM的唯一方法 元素。如果您将项目推送到列表或删除会发生什么 中间的东西?如果密钥与React假设之前相同 DOM元素表示与以前相同的组件。但那 不再是真的。
另一方面,在你的按钮上添加一个onClick,并传递你希望它作为App中的道具运行的功能。
<button onClick={() => this.props.handleClick(this.props.id)} />
和App.js
...
constructor(props) {
...
this.handleClick = this.handleClick.bind(this);
}
handleClick(id) {
// Do stuff
}
<ToDo
...
handleClick={this.handleClick}
/>
答案 1 :(得分:1)
您可以向onDelete
发送ToDo
道具:
const Todo = ({ description, id, isCompleted, toggleComplete, onDelete }) =>
<li>
<input
type="checkbox"
checked={isCompleted}
onChange={toggleComplete}
/>
<button onClick={() => onDelete(id)}>Destroy!</button>
<span>{description}</span>
</li>
来自App
:
<ToDo
// other props here
onDelete={this.deleteTodo}
/>
正如@Dakota指出的那样,在通过列表进行映射时使用索引作为键并不是一个好的模式。
也许只需更改您的initialState
并为其中的每一个设置id
:
this.state = {
todos: [
{ id: 1, description: 'Walk the cat', isCompleted: true },
{ id: 2, description: 'Throw the dishes away', isCompleted: false },
{ id: 3, description: 'Buy new dishes', isCompleted: false }
],
newTodoDescription: '',
}
这也使得从数组中删除项目变得更容易:
deleteTodo(id) {
this.setState((prevState) => ({
items: prevState.items.filter(item => item.id !== id),
}))
}