Reputation: 13
Hello why component in react was not rendering? State was updated and i see it in developer tools but content was not changing
FULL CODE: https://pastebin.com/bxNUAieV
import React, {useState} from 'react'
const List = (props:any) => {
const [actToDo, changeActTodo] = useState(props.actToDo)
const [ToDoLists, changeActToDoLists] = useState(props.ToDoLists)
return (
<>
{ToDoLists[actToDo].list.map((e:any, index:any) => (
<div className={'Todo__element'}>
<li key={index}>{e}</li><i className="fas fa-check"></i><i className="fas fa-recycle" onClick={() => props.removeElement(index)}></i>
</div>))}
</>
)
}
export default List
ToDoLists[number].list save the list actToDo save number
const removeElement = (index:any) => {
console.log(index);
let FullList = ToDoLists
//@ts-ignore
FullList[actToDo].list.splice(index,1)
changeToDoLists(FullList)
console.log(ToDoLists);
}
Upvotes: 0
Views: 115
Reputation: 1953
This is happening because, you are directly trying to update the same state array.
React compares the previous state with the updated state to decide if the component needs to be re-rendered. Modifying the state directly will disturb this process.
While updating:
Since you are updating the data inplace using splice at the previous state's address i.e. mutating the same array and the updating state, and the state TodoLists
is a complex object (nested array), so, React cant track the update and thus not detecting the state change.
While creating new item
This is not happening at the time of new item creation as you are not directly appending/ mutating the old state, therefore, the state got updating and react detects state change.
For removing the items, you can do is
const removeElement = (index) => {
console.log(index);
let FullList = [...ToDoLists]; //<-- create copy of the list
//@ts-ignore
FullList[actToDo].list = [...FullList[actToDo]].list.filter( //<-- filter the list by removing toBeRemoved Object
(_, i) => i !== index
);
console.log(FullList[actToDo]);
changeToDoLists(FullList); //update the state
};
Note
: Whi;e updating a complex object, always keep in mind to use ...
operator, which creates a shallow copy
of your object for updating. It works both for array
and object
.
Upvotes: 0
Reputation: 938
What I can see in your code is that you are directly modifying a state variable, which we should never do in React. To modify a state variable first make its copy in a new variable, and after making changes , pass that new variable in setState function :
So instead of :
let FullList = ToDoLists
do like this :
let FullList = _.cloneDeep(objects); //(using Lodash deep clone method here)
changeToDoLists(FullList);
Also , if you want to console your new list, then you should use useContext hook, since useState acts asynchronously and will not update value immediately, so console on very next line will not give updated value :
useEffect(() => {
console.log('Here is my new list after updation', ToDoLists);
}, [ToDoLists]);
Upvotes: 0
Reputation: 1036
you are mutating the array, that will not work, also the console.log
will display the wrong value as setState is async.
https://dev.to/il3ven/common-error-accidentally-mutating-state-in-react-4ndg
const removeElement = (index:any) => {
console.log(index);
let FullList = {
...ToDoLists,
[actToDo]: {
...ToDoLists[actToDo],
list: ToDoLists[actToDo].list.splice(index,1)
}
}
console.log(FullList);
changeToDoLists(FullList);
}
by the way, saving props to state is a bad behavior, as if the prop change nothing will happen.
Upvotes: 1