简体   繁体   English

如何使用钩子在我的 React 应用程序中编辑待办事项?

[英]How can I edit a todo in my react app using hooks?

I'm trying to figure out how to edit a todo item in my react app using hooks, but I can't seem to figure out how to write the code.我试图弄清楚如何使用钩子在我的 React 应用程序中编辑待办事项,但我似乎无法弄清楚如何编写代码。

Most of the solutions I've seen online are using class components and it's not written with the same logic as my app.我在网上看到的大多数解决方案都使用类组件,并且它的编写逻辑与我的应用程序不同。

Here is my current code这是我当前的代码

  function TodoList() {
        const [todos, setTodos] = useState([]);

        const addTodo = todo => {
          if (!todo.text || /^\s*$/.test(todo.text)) {
            return;
          }

          const newTodos = [todo, ...todos];

          setTodos(newTodos);
          console.log(newTodos);
        };

        const removeTodo = id => {
          const removedArr = [...todos].filter(todoId => todoId.id !== id);

          setTodos(removedArr);
        };

        const completeTodo = id => {
          let updatedTodos = todos.map(todo => {
            if (todo.id === id) {
              todo.isComplete = !todo.isComplete;
            }
            return todo;
          });
          setTodos(updatedTodos);
        };

        const editTodo = e => {
          setTodos(e.target.value);
        };

        return (
          <>
            <TodoForm onSubmit={addTodo} />
            {todos.map(todo => (
              <div>
                <div
                  key={todo.id}
                  className={todo.isComplete ? 'complete' : ''}
                  key={todo.id}
                  onClick={() => completeTodo(todo.id)}
                >
                  {todo.text}
                </div>
                <FaWindowClose onClick={() => removeTodo(todo.id)} />
              </div>
            ))}
          </>
        );
      }

Here is the code from the other component这是另一个组件的代码

        function TodoForm(props) {
          const [input, setInput] = useState('');

          const handleChange = e => {
            setInput(e.target.value);
          };

          const handleSubmit = e => {
            e.preventDefault();

            props.onSubmit({
              id: Math.floor(Math.random() * 10000),
              text: input,
              complete: false
            });
            setInput('');
          };

          return (
            <form onSubmit={handleSubmit}>
              <input
                placeholder='todo...'
                value={input}
                onChange={handleChange}
                name='text'
              />
              <button onClick={handleSubmit}>add todo</button>
            </form>
          );
        }

So right now everything works where I can add todos and delete todos + cross out todos.所以现在一切正常,我可以添加待办事项和删除待办事项+划掉待办事项。 Only thing missing is being able to edit them.唯一缺少的是能够编辑它们。

I saw some suggestions about updating the text value with an input form, but I'm not too sure how I'd implement that in my editTodo function.我看到了一些关于使用输入表单更新文本值的建议,但我不太确定如何在我的 editTodo 函数中实现它。

Similar to your removeTodo handler, you want to pass the todo.id to completeTodo.与您的 removeTodo 处理程序类似,您希望将 todo.id 传递给 completeTodo。

<div className={todo.isComplete ? "complete" : ""} key={todo.id} onClick={() => completeTodo(todo.id)}>

Then you would update a bool value in the todo object.然后您将更新 todo 对象中的 bool 值。

const completeTodo = (id) => {
   let updatedTodos = todos.map(todo => {
        if(todo.id === id){
            todo.isComplete = true
         }
       return todo
  }) 
    setTodos(updatedTodos)
};

Edit: add styling strikethrough You'll then conditionally add a css style based on isComplete boolean编辑:添加样式删除线然后您将有条件地添加基于 isComplete 布尔值的 css 样式

CSS CSS

.complete {
    text-decoration: line-through;
}

To be able to click on the Remove button, place it outside the todo div in your map function.为了能够单击“删除”按钮,请将其放在地图功能中的待办事项 div 之外。

{todos.map((todo, isComplete) => (
          <>
              <div
                key={todo.id}
                onClick={completeTodo}
                className={isComplete ? 'complete' : ''}
              >
                {todo.text}
                
              </div>
             <FaWindowClose onClick={() => removeTodo(todo.id)} />
         </>
 ))}

As discussion with you in another question here it is:在另一个问题中与您讨论时,它是:

TodoList.js TodoList.js

import React, { useState } from "react";
import TodoForm from "./TodoForm";
import Todo from "./Todo";

function TodoList({ onClick }) {
  const [todos, setTodos] = useState([]);
  //Track is edit clicked or not
  const [editId, setEdit] = useState(false);
  //Save input value in input box
  const [inputValue, setInputValue] = useState("");

  const handleEditChange = (id, text) => {
    setEdit(id);
    setInputValue(text);
  };
  const addTodo = (todo) => {
    if (!todo.text || /^\s*$/.test(todo.text)) {
      return;
    }

    const newTodos = [todo, ...todos];

    setTodos(newTodos);
    console.log(newTodos);
  };

  const removeTodo = (id) => {
    const removedArr = [...todos].filter((todoId) => todoId.id !== id);

    setTodos(removedArr);
  };

  const completeTodo = (id) => {
    let updatedTodos = todos.map((todo) => {
      if (todo.id === id) {
        todo.isComplete = !todo.isComplete;
      }
      return todo;
    });
    setTodos(updatedTodos);
  };

  const editTodo = (id, text) => {
    let editTodos = todos.map((todo) => {
      if (todo.id === id) {
        todo.text = text;
      }
      return todo;
    });
    setTodos(editTodos);
    setEdit(false);
  };

  return (
    <>
      <TodoForm onSubmit={addTodo} />
      {/* I want to move this code below into a new component called Todo.js */}
      <Todo
        todos={todos}
        completeTodo={completeTodo}
        removeTodo={removeTodo}
        editTodo={editTodo}
        handleEditChange={handleEditChange}
        editId={editId}
        inputValue={inputValue}
        setInputValue={setInputValue}
      />
    </>
  );
}

export default TodoList;



Todo.js待办事项.js

// I want to move this code into this component
import React, { useState } from "react";

import { FaWindowClose, FaRegEdit } from "react-icons/fa";

const Todo = ({
  todos,
  completeTodo,
  removeTodo,
  editTodo,
  editId,
  handleEditChange,
  inputValue,
  setInputValue
}) => {
  return todos.map((todo) => (
    <div className="todo-row">
      {editId === todo.id ? (
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
        />
      ) : (
        <div
          key={todo.id}
          className={todo.isComplete ? "complete" : ""}
          onClick={() => completeTodo(todo.id)}
        >
          {todo.text}
        </div>
      )}
      {editId === todo.id ? (
        <button onClick={() => editTodo(todo.id, inputValue)}>Edit todo</button>
      ) : (
        <>
          <FaWindowClose onClick={() => removeTodo(todo.id)} />
          <FaRegEdit onClick={() => handleEditChange(todo.id, todo.text)} />
        </>
      )}
    </div>
  ));
};

export default Todo;

Make sure you read and understand code first.确保您首先阅读并理解代码。 Logic is pretty simple what you do in completeTodo .您在completeTodo 中所做的事情的逻辑非常简单。 You just need to update text part.您只需要更新文本部分。 Tricky part is to open in input.棘手的部分是在输入中打开。 So logic is like track if user click on id set that id.因此,如果用户单击 id 设置该 id,逻辑就像跟踪。 And check if id is there open input with that id value other wise normal one.并检查 id 是否存在具有该 id 值的打开输入,否则正常。

Here is demo of this POC: https://codesandbox.io/s/nostalgic-silence-idm21?file=/src/Todo.js:0-1059这是这个 POC 的演示: https : //codesandbox.io/s/nostalgic-silence-idm21? file =/ src/Todo.js: 0-1059

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM