0

I have a simple todo list that consists of multiple inputs.

I made the editing functionality and now everything works as it should, but only once. When I change the input data for the first time, it saves everything to an array with the correct data.

And when I want to do it a second time, then in order to save this data, three inputs must be changed.

I want that even when changing one input, the data is saved in an array (data that has not been changed is overwritten).

Stackblitz code

App.js

function App(props) {
  const [tasks, setTasks] = useState(props.tasks);
  
  function editTask(id, newName, newTranslate, newNote) {
    const editedTaskList = tasks.map((task) => {
      if (id === task.id) {
        return { ...task, name: newName , translate: newTranslate , note: newNote  };
      }
      return task;
    });
    setTasks(editedTaskList);
  }

  const taskList = tasks
    .map((task) => (
      <Todo
        id={task.id}
        name={task.name}
        translate={task.translate}
        note={task.note}
        completed={task.completed}
        key={task.id}
        editTask={editTask}
        tasks={tasks}
      />
    ));
  return (
    <div className="todoapp stack-large">
      <ul
        className="todo-list stack-large stack-exception"
        aria-labelledby="list-heading">
        {taskList}
      </ul>
    </div>
  );
}

export default App;

I did a check and added the save button onClick which outputs the data to the console. It gives the data correctly the first time, and if the same item in the todo is changed the second time, it gives an empty space instead of the data that has not been changed.

Todo.js

export default function Todo({name, translate, note, editTask, id, tasks}) {
  const [isEditing, setEditing] = useState(false);
  const [newName, setNewName] = useState(name);
  const [newTranslate, setNewTranslate] = useState(translate);
  const [newNote, setNewNote] = useState(note);

  function handleChange(e) {
    setNewName(e.target.value)
  }
  function handleChangeTranslate(e) {
    setNewTranslate(e.target.value);
  }
  function handleChangeNote(e) {  
        setNewNote(e.target.value)
  }

  function handleSubmit(e) {
    e.preventDefault();
    if (!newName.trim()|| !newTranslate.trim() || !newNote.trim()) {
      return;
    }
    editTask(id, newName,newTranslate,newNote);
    setNewName("");
    setNewTranslate("");
    setNewNote("");
    setEditing(false);
  }
  

  const editingTemplate = (
    <form className="stack-small" onSubmit={handleSubmit}>
      <div className="form-group">
        <input
          id={id}
          className="todo-text"
          type="text"
          autoComplete='off'
          defaultValue={newName || name}
          onChange={handleChange}
          placeholder="write word"
        />
        <input
          id={id}
          className="todo-text"
          type="text"
          autoComplete='off'
          defaultValue={newTranslate || translate}
          onChange={handleChangeTranslate}
          placeholder="write translate"
        />
        <input
          id={id}
          className="todo-text"
          type="text"
          autoComplete='off'
          defaultValue={newNote || note}
          onChange={handleChangeNote}
          placeholder="write note"
        />
        
      </div>
      <div className="btn-group">
        <button
          type="button"
          className="btn todo-cancel"
          onClick={() => setEditing(false)}
        >
          Cancel
        </button>

        <button type="submit" className="btn btn__primary todo-edit" onClick={()=>console.log(newName, newTranslate, newNote)}>
          Save
        </button>
      </div>
    </form>
  );

  const viewTemplate = (
    <div className="stack-small">
      <div className="c-cb">
          <label className="todo-label" htmlFor={id}>
            {name}
          </label>
          <label className="todo-label" htmlFor={id}>
            {translate}
          </label>
          <label className="todo-label" htmlFor={id}>
            {note}
          </label>
          
        </div>
        <div className="btn-group">
        <button
          type="button"
          className="btn"
          onClick={() => setEditing(true)}
          >
            Edit <span className="visually-hidden">{name}</span>
          </button>
        
        </div>
    </div>
  );
  return <li className="todo">{isEditing ? editingTemplate : viewTemplate}</li>;
}
2
  • Did you mean you want to keep the preview state which is not edited to print out or you want to print out those inchanged state to a empty string ? Commented Jan 20, 2023 at 14:06
  • I want that I need to edit the data in one input, it was saved, and the data of other inputs that were not changed remained the same. and it works but only once, and the second time if try to change the data in the same todo task, in order to save the data, you need to change three inputs. Commented Jan 20, 2023 at 14:09

1 Answer 1

1

Since you want to keep those preview state which was not edit and still print out those state with the one you edit, you can just remove all the "reset state '' you put, since all your initial state from useState already had a value and is not an empty string "" like this

   function handleSubmit(e) {
    e.preventDefault();
    if (!newName.trim()|| !newTranslate.trim() || !newNote.trim()) {
      return;
    }
    editTask(id, newName,newTranslate,newNote);
    setEditing(false);
  }
Sign up to request clarification or add additional context in comments.

1 Comment

Wow thanks! This is exactly what I needed! I just didnt think that it could affect, although it is logical that it can. Thank you sm

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.