So I have this state in the parent component
export const parent = () => {
const [categorySets, setCategorySets] = useState<any>();
//categorySets being
/*
{
{category_set_id: 1, name: "name1", el: []},
{category_set_id: 2, name: "name2", el: []},......
}
*/
//function to update el inside categorySets
const setSubcategory = async (id : any) => {
//id 1
let response = await service.getCategories(id);
//response === [{el: 1, name: "name1"},{el: 2, name: "name2"}]
const indexArrToPush = categorySets.findIndex(
(item: any) => item.category_set_id === id
);
if (indexArrToPush > -1){
let localCatSets = categorySets
let catSetsToMod = localCatSets[indexArrToPush]
catSetsToMod.el = [
...response
]
localCatSets[indexArrToPush] = catSetsToMod
//localsets being
/*
{
{category_set_id: 1, name: "name1", el: [{el: 1, name: "name1"},{el: 2, name: "name2"}]},
{category_set_id: 2, name: "name2", el: []},......
}
*/
setCategorySets(localCatSets)
}
}
return (
{categorySets &&
categorySets.length > 0 &&
categorySets.map((i: any) => {
return (
<PublicationCategoryRow
name={i.name}
key={i.category_set_id}
el={i.el} //this is the important part, in the first render its empty for every element, because I havent set it yet
assign={true}
categorySetOptions={categorySetOptions}
assignedCategory={assignedCategory}
setAssignedCategory={setAssignedCategory}
i={i}
setSubcategory={setSubcategory}
/>
);
})}
)
}
const PublicationCategoryRow = ({el, i}) => {
const [names] = useState(el);
useEffect(() => {
console.log("names updated")
console.log(names)
}, [names]) //WHY IS THIS NOT BEING UPDATED? WHEN IM CLICKING THE BELOW ONCLICK AND UPDATING el PROP?
return(
<Box onClick={() => somevaribale && setSubcategory(i.category_set_id)}/> //this is effectively triggering the function in the parent component and updating the state
)
}
I have the above flow with 2 components
Pretty much, I pass a el
element for every child component, this el
element is an instance of the array of objects categorysets
.
I update the main object categorysets
from within the child component, but it does not rerender the childrens.
Whats the issue?
CodePudding user response:
your dependencies list for the useEffect is only the 'names' state you set, it means that your useEffect will only rerun when 'names' changes. in your case, it doesn't happen. because once you set it it never changes again.
you should add the 'el' element, then it will work like 'getDerivedStateFromProps' in a class component. which means, every time el will change, the useEffect will be triggered.
side notes:
- if you keep the dependencies array empty, it will trigger only once! in the initial render of the component
- if you remove it, it will trigger each time the component re-renders
important: if you are using a state as a dependency, pay attention that you are not setting it there too, because you will get into infinite loop.
CodePudding user response:
Ok, I think I got it. You are directly trying to set names state
and I think that's why it is not working try doing it using the following code:
const PublicationCategoryRow = ({el, i}) => {
const [names, setNames] = useState();
useEffect(() => {
setNames((prevState) => {...prevState, el})
console.log("names updated")
console.log(names)
}, [el])
return(
<Box onClick={() => somevaribale &&
setSubcategory(i.category_set_id)}/>
)
}
CodePudding user response:
The issue was that I was directly mutating the array
if (indexArrToPush > -1){
let localCatSets = categorySets
must be
if (indexArrToPush > -1){
let localCatSets = [...categorySets]