Ayyappa Gollu
Ayyappa Gollu

Reputation: 966

react page not re-rendering when state updates

i have implemented a todolist app using react hooks. i have two states here. one is a name state which holds value of textfield. one more is List state which holds the content of todo list as an array.

now when i add items , i update List state and page re-renders fine. but when i remove a selected item, i update the List array , and it does update as i checkedlogs and it re-renders again .. but i can't see the change on UI. so in a nutshell remove an item handler is not working in my code.

import React,{useState} from "react"
import {render} from "react-dom"

const  App = ()=> {

    const [taskList, setTaskList] = useState([])
    const [taskField, setTaskField] = useState("");

    function handleTaskFieldChange(e){
        setTaskField(e.target.value);
    }

    function handleAddClick(){
        if(taskField){
             setTaskList([...taskList, taskField])
             setTaskField("")
        }
    }

    function removeButtonHandler(e){
        var i = e.target.id;
        var list = taskList;
        list.splice(i,1)
        console.log(list)
        setTaskList(list)
    }

    return(
        <div>
            <div>
               <b> TO DO LIST</b>
            </div>
            <div 
            className= "inputAdd">
                <input
                value={taskField}
                placeholder="enter new task "
                onChange = {handleTaskFieldChange} >
                </input>
                <button                
                onClick = {handleAddClick}
                >
                    Add +
                </button>
            </div>
            {
            taskList.map((element,index) =>  {
                console.log("repaint list", taskList)
                return(
                <div
                className="listItem"
                key={index}>
                <span>{index + 1}. {element}</span>
                <button
                key={index}
                id={index}
                onClick={removeButtonHandler}
                >
                    remove
                </button>
            </div>)

                })
            }
        </div>
    )
}

render(<App/>, document.getElementById("root"))

can you guys tell me what is wrong with my remove button hanlder ? why it's not rendering updated list after removing an item.?

Upvotes: 0

Views: 51

Answers (2)

Sanaullah
Sanaullah

Reputation: 374

you may use spreed operator to iterate the list. you were a mistake where you assign taskList to the list variable.use the following code

function removeButtonHandler(e) {
        var i = e.target.id;
        var list = [...taskList];
        list.splice(i, 1)
        console.log(list)
        setTaskList(list)
    }

Upvotes: 1

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15688

Try to avoid directly mutating the state object by using .splice(). For React to render with the updated state correctly, you want to pass in a completely new state object.

Upon triggering removeButtonHandler, we can use .filter() to create a new list of items, not including the item you selected to remove. Then pass that new list to setTaskList()

Working sandbox: https://codesandbox.io/s/dawn-frog-gv79h

import React, { useState } from "react";
import ReactDOM from "react-dom";

const App = () => {
  const [taskList, setTaskList] = useState([]);
  const [taskField, setTaskField] = useState("");

  function handleTaskFieldChange(e) {
    setTaskField(e.target.value);
  }

  function handleAddClick() {
    if (taskField) {
      setTaskList([...taskList, taskField]);
      setTaskField("");
    }
  }

  function removeButtonHandler(e) {
    var i = e.target.id;
    const updatedTasks = taskList.filter(
      (field, fieldIndex) => fieldIndex != i
    );
    setTaskList(updatedTasks);
  }

  return (
    <div>
      <div>
        <b> TO DO LIST</b>
      </div>
      <div className="inputAdd">
        <input
          value={taskField}
          placeholder="enter new task "
          onChange={handleTaskFieldChange}
        />
        <button onClick={handleAddClick}>Add +</button>
      </div>
      {taskList.map((element, index) => {
        return (
          <div className="listItem" key={index}>
            <span>
              {index + 1}. {element}
            </span>
            <button key={index} id={index} onClick={removeButtonHandler}>
              remove
            </button>
          </div>
        );
      })}
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Upvotes: 3

Related Questions