const [item, setItem] = useState("")
const [itemList, setItemList] = useState([])
const [actualItem, setActualItem] = useState([])
function addItem(){
setItemList([...itemList , item])
setActualItem([...itemList , item])
setItem("")
}
function filterVal(e){
const filteredArr = itemList.filter((item)=> item.includes(e.target.value))
if (filteredArr.length !== 0 && e.target.value.length > 3) {
setItemList(filteredArr)
} else {
setItemList(actualItem)
}
}
console.log("render")
function removeItem(e){
const val = itemList.indexOf(e.target.parentElement.firstElementChild.innerText)
itemsArr = itemList
itemsArr.splice(val, 1)
console.log(itemsArr)
setItemList(itemsArr)
}
return (
<div className="body">
<div className="search">
<input type="text" onChange={filterVal} placeholder="Search Here"/>
</div>
<div className="addItem">
<input type="text" placeholder="Add here" value={item} onChange={(e)=>{setItem(e.target.value)}}/>
<button className="btn" onClick={addItem}>Add Item</button>
<ul className="display">
{
itemList.length === 0 ? <h1>No Items</h1> :
itemList.map((item, index)=>{
return (
<div className="li" key={index} id={index}>
<li>{item}</li>
<p onClick={removeItem}>✖</p>
</div>
)
})
}
</ul>
<button className="clearBtn" onClick={()=>{setItemList([]); setActualItem([])}}>Clear All</button>
</div>
</div>
)
I am building a todo list using react. Adding, clear all and search functionality are working fine. But the removeItem is not working. When i click on the cross button, it should splice the array of items and update the actual state. But it is not. The state is updating but it is not getting reflected in the map function
2
Answers
Maybe you can try this code instead
Your code is almost working, but the issue happens at how JS compares objects/arrays.
In your
removeItem
method, you have the right thinking to copy the value of the stateitemList
to a temporary valueitemArr
. HOWEVER, what you did here is actually copied the reference/address of theitemList
, and is mutating it directly (which is a bad practice, but you had the right idea according to how you code, so thumbs up for that).When the state is updated in
setItemList(itemsArr)
, React makes a comparison of the state’sitemList
, turns out the value that you have previously passed in insetItemList
is exactly the same!(See "Referential Equality" section of this article for more info https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#1-referential-equality)
What you are supposed to do is, declare a new variable, COPY the value of the
itemList
instead of the reference, run your logic, then finally set the state withsetItemList(itemsArr);
so React will realize that the value of the stateitemList
has actually been updated, and finally cause a rerender, updating the UI.This is the fix to your
removeItem
method —See your work in action in CodeSandbox — https://codesandbox.io/s/great-marco-f4pkd5?file=/src/App.tsx