Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

While creating a to-do-list in React JS. I am getting – ( Cannot update a component (`App`) while rendering a different component (`DisplayTasks`) )

This is my Textinserter.js

In this JS file I have a text field to enter the task and a button to add that task to a tasks array

// Import React and useState from the 'react' library
import React, { useState } from "react";

// Create a functional component named Textinserter
export default function Textinserter({ tasks, setTasks }) {
  // Initialize state variables using useState hook: tasks and tasksInput
  const [tasksInput, setTasksInput] = useState("");

  // Function to handle changes in the input field
  const handleOnChange = (e) => {
    // Update tasksInput state with the value entered in the input field
    setTasksInput(e.target.value);
  };

  // Function to add a task to the tasks list
  const addTask = () => {
    // Check if the trimmed input is not an empty string
    if (tasksInput.trim() !== "") {
      // Create a new task object with an ID and name
      const newTask = { id: tasks.length + 1, name: tasksInput };

      // Update tasks state using the functional form of setTasks
      setTasks((prevTasks) => [...prevTasks, newTask]);

      // Clear the tasksInput state after adding the task
      setTasksInput("");
    }
  };

  // Return JSX for the component
  return (
    <>
      <div className="mb-3">
        {/* Input field and label */}
        <label htmlFor="exampleInputEmail1" className="form-label">
          Enter The Task
        </label>
        <input
          type="text"
          className="form-control"
          id="exampleInputEmail1"
          aria-describedby="emailHelp"
          onChange={handleOnChange} // Handle input changes with handleOnChange function
          value={tasksInput}
        />
        {/* Button to add a task */}
        <div className="conatiner text-center">
          <button className="btn btn-danger my-3" onClick={addTask}>
            Add Task
          </button>
        </div>
      </div>
    </>
  );
}

This is the Displaytasks.js

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This code displays the tasks inside the Tasks array and also has a delete Button which should delete a particular task. But I am getting a warning –

import React from "react";

// Component to display tasks
export default function DisplayTasks({ tasks, onDelete }) {
  const deleteTask = (taskId) => {
    // Filter out the task with the matching ID and update tasks array
    const updatedTasks = tasks.filter((task) => task.id !== taskId);
    onDelete(updatedTasks);
  };

  // Styling for the main container
  const myStyle = {
    backgroundColor: "#0D6EFD",
    padding: "15px",
    borderRadius: "10px",
  };

  return (
    <div
      // Conditional styling based on the tasks length
      style={
        tasks.length === 0 ? { ...myStyle, visibility: "hidden" } : myStyle
      }
    >
      {/* Heading for the tasks */}
      <h1 className="text-center text-light mb-4">Today's Tasks</h1>

      {tasks && tasks.length > 0 ? ( // Check if tasks exist and not empty
        <ul className="list-group" style={{ width: "100%" }}>
          {tasks.map((task) => (
            <div
              key={task.id}
              className="d-flex justify-content-between align-items-center"
            >
              {/* Container for each task */}
              <span
                className="d-inline-block w-100 overflow-hidden m-2"
                style={{ borderRadius: "10px" }} // Styling for each task container
              >
                {/* List item for the task */}
                <li className="list-group-item" aria-current="true">
                  {task.name}
                </li>
              </span>
              {/* Button to delete the task */}
              <button className="btn btn-danger" onClick={deleteTask(task.id)}>
                Delete
              </button>
            </div>
          ))}
        </ul>
      ) : (
        // Display if tasks array is empty or undefined
        <p>No tasks available</p>
      )}
    </div>
  );
}

App.js:10 Warning: Cannot update a component (App) while rendering a different component (DisplayTasks). To locate the bad setState() call inside DisplayTasks, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
at DisplayTasks (http://localhost:3000/static/js/bundle.js:122:3)
at div
at App (http://localhost:3000/static/js/bundle.js:33:76)

This is my App.js

import "./App.css";
import Textinserter from "./Components/Textinserter";
import DisplayTasks from "./Components/DisplayTasks";
import { useState } from "react";

export default function App() {
  const [tasks, setTasks] = useState([]); // Define tasks and setTasks in App component

  const handleTaskDeletion = (updatedTasks) => {
    setTasks(updatedTasks);
  };

  return (
    <div className="container mt-5">
      <Textinserter tasks={tasks} setTasks={setTasks} />
      <DisplayTasks tasks={tasks} onDelete={handleTaskDeletion} />
    </div>
  );
}

>Solution :

I haven’t tried to run the code myself, but it seems like the problem is in your DisplayTasks component.

below is your original code..

import React from "react";

// Component to display tasks
export default function DisplayTasks({ tasks, onDelete }) {
  const deleteTask = (taskId) => {
    // Filter out the task with the matching ID and update tasks array
    const updatedTasks = tasks.filter((task) => task.id !== taskId);
    onDelete(updatedTasks);
  };

  return (
    // ...
      <button className="btn btn-danger" onClick={deleteTask(task.id)}>
        Delete
      </button>
    // ...
  );
}

your deleteTask function updates the state of App component, and it is called during render, since you have put deleteTask(task.id) into button’s onClick prop.

onClick should be a function that should be ran when it is clicked. instead, you are calling a deleteTask function and it’s return (which is void) is given as a prop.

you just have to change it to a anonymous function, like below

import React from "react";

// Component to display tasks
export default function DisplayTasks({ tasks, onDelete }) {
  const deleteTask = (taskId) => {
    // Filter out the task with the matching ID and update tasks array
    const updatedTasks = tasks.filter((task) => task.id !== taskId);
    onDelete(updatedTasks);
  };

  return (
    // ...
      <button className="btn btn-danger" onClick={() => deleteTask(task.id)}>
        Delete
      </button>
    // ...
  );
}

or, maybe you could change your deleteTask function to return a function and use it.

import React from "react";

// Component to display tasks
export default function DisplayTasks({ tasks, onDelete }) {
  const deleteTask = (taskId) => () => {
    // Filter out the task with the matching ID and update tasks array
    const updatedTasks = tasks.filter((task) => task.id !== taskId);
    onDelete(updatedTasks);
  };

  return (
    // ...
      <button className="btn btn-danger" onClick={deleteTask(task.id)}>
        Delete
      </button>
    // ...
  );
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading