首页 > 解决方案 > 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.

标签: reactjs

解决方案


我想我需要在应用程序中创建一个 editTodo 方法并将其作为道具传递给列表,然后传递给 todoItem。

这正是您需要做的。但是:

  1. editTodo方法没有逻辑。
  2. ToDoList组件接收editingTodo方法作为道具而不是定义editTodo
  3. 您确实将editingTodo进一步传递给ToDoItem但您没有在那里使用它const ToDoItem = ({todo, deleteTodo}) => ...
  4. onClick在铅笔图标上没有监听器,因此不会发生任何事情。
  5. 我不知道您打算如何进行编辑(带有表单的模态窗口,或用输入字段替换文本),无论哪种方式,底线是您需要使用() => editTodo(id, newText).

我的建议是 - 解决以上所有 5 点,现在只需硬编码新值,只是为了测试它:() => editTodo(id, 'updated value!')并检查一切是否正常。作为下一步,您可以担心在那里获得真正的价值。


推荐阅读