Reputation: 11
Hello guys im having a bit of trouble with this, I have found some topics on here but none seem to be helping anyways this is my problem. I need to create a delete button as well as a delete todo method on the app components using an array of .filter, and then pass it to the ToDo component as a prop, as well as Add an onClick event listener to the delete button, and have it call deleteTodo, passing it the index of the to-do.
import React, { Component } from 'react';
import './App.css';
import ToDo from './components/ToDo.js';
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [
{ description: 'Walk the cat', isCompleted: true},
{ description: 'Throw away the dishes', isCompleted: false},
{ description: 'Buy new dishes', isCompleted: false}
],
newTodoDescription: ''
};
}
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>
);
}
}
export default App;
import React, {Component} from 'react';
class ToDo extends Component {
render() {
return (
<li>
<input type="checkbox" checked={ this.props.isCompleted } onChange={ this.props.toggleComplete } />
<span> { this.props.description }</span>
</li>
);
}
}
export default ToDo;
Upvotes: 1
Views: 910
Reputation: 112777
You can create a new method deleteTodo
in App
that takes in the todo
object you want to remove and filter that out from the state.
Since the order of todos
will now change, you can no longer use the array index as key
for the Todo
components. You can add an id
to your todo objects and use that instead.
Example
class App extends React.Component {
state = {
todos: [
{ id: Math.random(), description: "Buy new dishes", isCompleted: false }
],
newTodoDescription: ""
};
handleChange(e) {
this.setState({ newTodoDescription: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (!this.state.newTodoDescription) {
return;
}
const newTodo = {
id: Math.random(),
description: this.state.newTodoDescription,
isCompleted: false
};
this.setState({
todos: [...this.state.todos, newTodo],
newTodoDescription: ""
});
}
toggleComplete(todo) {
this.setState({
todos: this.state.todos.map(t => {
if (t !== todo) {
return t;
}
return { ...t, isCompleted: !t.isCompleted };
})
});
}
deleteTodo(todo) {
this.setState({ todos: this.state.todos.filter(t => t !== todo) });
}
render() {
return (
<div className="App">
<ul>
{this.state.todos.map(todo => (
<ToDo
key={todo.id}
description={todo.description}
isCompleted={todo.isCompleted}
toggleComplete={() => this.toggleComplete(todo)}
deleteTodo={() => this.deleteTodo(todo)}
/>
))}
</ul>
<form onSubmit={e => this.handleSubmit(e)}>
<input
type="text"
value={this.state.newTodoDescription}
onChange={e => this.handleChange(e)}
/>
<input type="submit" />
</form>
</div>
);
}
}
class ToDo extends React.Component {
render() {
return (
<li>
<input
type="checkbox"
checked={this.props.isCompleted}
onChange={this.props.toggleComplete}
/>
<span> {this.props.description}</span>
<button onClick={this.props.deleteTodo}>Delete</button>
</li>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 1