reactjs - How to edit a todo in a todo list without hooks and redux
问题描述
I have been stuck on this for days reading up on tutorials and articles but can not figure this out. Whenever I click on the pencil icon, I want it to edit the current do to. I have 4 components, the form (searchbar where i add todo), the app.js, the todoList, and a todo.js component. I am keeping all the state in the app and state in the form to keep track of the terms I am entering.
I am thinking I would need to create an editTodo method in the app and pass it down as a prop to the list and then the todoItem. Most tutorials or help online uses hooks or redux but I am learning vanilla React first. I am not asking for the answer directly but rather the steps or thought process to implement editing a todo item in the todolist. I am not sure even if my todo app is correct in the places where I am keeping state. I may get slack for asking.. but I do not know what else to do. Here is my code..
class App extends React.Component {
state = {
todos: []
}
addTodo = (todo) => {
const newToDos = [...this.state.todos, todo];
this.setState({
todos: newToDos
});
};
deleteTodo = (id) => {
const updatedTodos = this.state.todos.filter((todo) => {
return todo.id !== id;
});
this.setState({
todos: updatedTodos
});
}
editTodo = (id, newValue) => {
}
render() {
return (
<div className="container">
<div className="row">
<div className="col">
<Form addTodo={this.addTodo} />
</div>
</div>
<div className="row">
<div className="col">
<ToDoList
todos={this.state.todos}
deleteTodo={this.deleteTodo}
editingTodo={this.state.editingTodo}/>
</div>
</div>
</div>
)
}
}
export default App;
const ToDoList = ({todos, deleteTodo, editingTodo}) => {
const renderedList = todos.map((todo, index) => {
return (
<ul className="list-group" key={todo.id}>
<ToDoItem todo={todo} deleteTodo={deleteTodo} editingTodo={editingTodo}/>
</ul>
)
});
return (
<div>
{renderedList}
</div>
)
}
export default ToDoList;
const ToDoItem = ({todo, deleteTodo}) => {
return (
<div>
<li style={{display: 'flex', justifyContent: 'space-between' }} className="list-group-item m-3">
{todo.text}
<span>
<FontAwesomeIcon
icon={faPencilAlt}
style={{ cursor: 'pointer'}}
/>
<FontAwesomeIcon
icon={faTrash}
style={{ marginLeft: '10px', cursor: 'pointer'}}
onClick={ () => deleteTodo(todo.id)}
/>
</span>
</li>
</div>
);
}
export default ToDoItem;
I don't think the form component is relevant here as I am trying to edit a todo item so will not include it here. If I do need to include it, let me know. It may not look like I have tried to implement this functionality, but either I could not find what I was looking for, understand the code, or just do not know how to implement it.
Update:
I added an isEditing field in the form component to my todo items so that maybe it can help me know if an item is being editing or not. I also redid the editTodo method.
class Form extends React.Component {
state = { term: ''};
handleSubmit = (e) => {
e.preventDefault();
this.props.addTodo({
id: shortid.generate(),
text: this.state.term,
isEditing: false
});
this.setState({
term: ''
});
}
editTodo = (id, newValue) => {
const editedTodos = [...this.state.todos].map((todo) => {
if(todo.id === id) {
todo.isEditing = true;
todo.text = newValue;
}
return todo.text;
});
this.setState({
todos: [...this.state.todos, editedTodos]
});
}
I also passed that method down to the todoList and then to the todoItem like so
const ToDoItem = ({todo, deleteTodo, editTodo}) => {
const renderContent = () => {
if(todo.isEditing) {
return <input type='text' />
} else {
return <span>
<FontAwesomeIcon
icon={faPencilAlt}
style={{ cursor: 'pointer'}}
onClick={ () => editTodo(todo.id, 'new value')}
/>
<FontAwesomeIcon
icon={faTrash}
style={{ marginLeft: '10px', cursor: 'pointer'}}
onClick={ () => deleteTodo(todo.id)}
/>
</span>
}
}
return (
<div>
<li style={{display: 'flex', justifyContent: 'space between'}} className="list-group-item m-3">
{{!todo.isEditing ? todo.text : ''}}
{renderContent()}
</li>
</div>
);
}
So whenever I click on the the edit icon, it successfully shows 'new value' but now also adds an extra todo item which is blank. I figured out how to add the input field so that it shows also. I am accepting the answer Brian provided since it was the most helpful in a lot of ways but have not completed the functionality for editing a todo.
解决方案
我想我需要在应用程序中创建一个 editTodo 方法并将其作为道具传递给列表,然后传递给 todoItem。
这正是您需要做的。但是:
editTodo
方法没有逻辑。ToDoList
组件接收editingTodo
方法作为道具而不是定义editTodo
。- 您确实将
editingTodo
进一步传递给ToDoItem
但您没有在那里使用它const ToDoItem = ({todo, deleteTodo}) => ...
- 您
onClick
在铅笔图标上没有监听器,因此不会发生任何事情。 - 我不知道您打算如何进行编辑(带有表单的模态窗口,或用输入字段替换文本),无论哪种方式,底线是您需要使用
() => editTodo(id, newText)
.
我的建议是 - 解决以上所有 5 点,现在只需硬编码新值,只是为了测试它:() => editTodo(id, 'updated value!')
并检查一切是否正常。作为下一步,您可以担心在那里获得真正的价值。
推荐阅读
- c# - 如何在 C# 中删除嵌套 json 结构中的键值对
- solr - solr 中的 maxcommittokeep value=1 配置
- c# - 无法使用“https://accounts.google.com/o/oauth2/v2/auth?access_type=offline”启动浏览器
- python - 如何在 tensorflow 对象检测 API 中更改默认输出、输入张量名称?
- php - 当laravel使用图像干预调整图像大小时超出内存限制
- java - 为什么我的无障碍服务没有启动?
- docker - 从存储库中拉取
- javascript - Highcharts甘特图:不支持Y轴上的父子功能与Y轴配置上的类别声明
- android - 如何在android中更改送货地址时进行动态付款更新
- java - 大 O 表示法(算法)