Search code examples
reactjsinfinite-looplifecycle

Reactjs. Edit task features infinity loop?


I try to build a simple dummy toDo app, my issue occurs after I had set up the feature for editing a specific todo item. According to the warning that I get from the browser, it seems that I ran into an infinite loop ? I try now to figure out where it occurs however sadly I couldn't find it so far.

Is there someone to give me more insight about this pls? Thanks in advance :

import React, { useState, useEffect } from "react";
import { Form, TasksContainer, TaskWrapper } from "../styledApp";

// ========= STARTING POINT =========

const SearchInput = () => {
  // ========= STATES & EFFECTS =========

  const [taskValue, setTaskValue] = useState("");
  const [allTasks, setAllTasks] = useState(() => {
    const persistedTasks = localStorage.getItem("tasks");
    if (persistedTasks) {
      return JSON.parse(persistedTasks);
    } else {
      return [];
    }
  });
  const [currentTask, setCurrentTask] = useState({});
  const [isEditing, setIsEditing] = useState(false);

  useEffect(() => {
    localStorage.setItem("tasks", JSON.stringify(allTasks));
  }, [allTasks]);

  // ========= FUNCTIONS =========

  // ========= add related =========

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

  const handleSubmit = (e) => {
    e.preventDefault();
    if (taskValue !== "") {
      setAllTasks([
        ...allTasks,
        { id: allTasks.length + 1, text: taskValue.trim() },
      ]);
    }
    setTaskValue("");
  };

  // ========= delete related =========

  // ***** not created yet *****

  // ========= edit related =========

  const handleEditClick = (todo) => {
    setIsEditing(true);
    setCurrentTask({ ...todo });
  };

  const handleChangeEditInput = (e) => {
    setCurrentTask({ ...currentTask, text: e.target.value });
  };

  const handleUpdateTodo = (id, updatedTodo) => {
    const updatedItem = allTasks.map((todo) => {
      return todo.id === id ? updatedTodo : todo;
    });
    setIsEditing(false);
    setAllTasks(updatedItem);
  };

  const handleEditFormSubmit = (e) => {
    e.preventDefault();
    handleUpdateTodo(currentTask.id, currentTask);
  };

  // ========= JSX RENDERING =========

  return (
    <>
      {isEditing ? (
        <Form>
          <input
            name="editTodo"
            type="text"
            placeholder="Edit the task..."
            value={currentTask.text}
            onChange={handleChangeEditInput}
          />
          <button type="submit" onClick={handleEditFormSubmit}>
            Update the Task
          </button>
          <button onClick={() => setIsEditing(false)}>Cancel</button>
        </Form>
      ) : (
        <Form onSubmit={handleSubmit}>
          <input
            type="text"
            placeholder="Add a task..."
            value={taskValue}
            onChange={handleChange}
          />
          <button type="submit">Submit the Task</button>
        </Form>
      )}

      <TasksContainer>
        {!allTasks.length && <p>No tasks</p>}
        {!!allTasks.length && (
          <ul>
            {allTasks.map((task) => (
              <div key={task.id}>
                <TaskWrapper>
                  <li>{task.text} </li>
                  <div>
                    <button
                      id={task.id}
                      value={task.text}
                      onClick={handleEditClick(task)}
                    >
                      Edit
                    </button>
                    <button>Delete</button>
                  </div>
                </TaskWrapper>
              </div>
            ))}
          </ul>
        )}
      </TasksContainer>
    </>
  );
};

export default SearchInput;

Solution

  • That's because of the edit button

     <button
            id={task.id}
            value={task.text}
            onClick={handleEditClick(task)} >
            Edit
    </button>
    

    onClick should be function reference, like

    onClick={(_) => handleEditClick(task)}