Home > Back-end >  empty data instead of data from the array when changing the data in the input react js
empty data instead of data from the array when changing the data in the input react js

Time:01-21

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>;
}

CodePudding user response:

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);
  }
  • Related