Reputation: 966
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
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
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