I have a functional component that needs to be updated.
export const VendorCategory = ({setShowProgress, user}) => {
const classes = useStyles()
const theme = useTheme()
const listElements = []
const [dummyCategory, setDummyCategory] = useState({
"Test1": [
"Subtest1", "Subtest2", "Subtest3"
],
"Test2": [
"Subtest1", "Subtest2", "Subtest3"
],
"Test3": [
"Subtest1", "Subtest2", "Subtest3"
]
})
useEffect(() => {
return () => {
console.log("re-rendered")
}
})
const AddSubCategory = useCallback(() => {
setShowProgress(true)
const newAdd = dummyCategory['Test1']
newAdd.push("SubTest4")
setDummyCategory({...dummyCategory, "Test1": newAdd})
setShowProgress(false)
},[setShowProgress,setDummyCategory,dummyCategory])
return (
<div className={classes.root}>
<h3 className={classes.title}>Vendor Category</h3>
<Button
className={classes.button}
variant='contained'
color="primary"
>
Add Category
</Button>
<div className={classes.categoryDiv}>
{
Object.keys(dummyCategory).map((value, index) => {
return (
<List>
<Accordion key={uuid()} mt={2}>
<AccordionSummary
expandIcon={<ExpandMoreIcon/>}
aria-controls="panel1a-content"
id="panel1a-header"
>
<ListSubheader key={uuid()} className={classes.sublistHeader} component="div"
id="nested-list-subheader">
{value}
</ListSubheader>
</AccordionSummary>
<AccordionDetails className={classes.subCategoryList}>
<Button
className={classes.button}
variant='contained'
color="primary"
onClick={AddSubCategory}
>
Add Sub-Category
</Button>
{dummyCategory[value].map((subvalue, index) => {
return (
<ListItem button key={subvalue}>
<ListItemText inset primary={subvalue}/>
</ListItem>
)
})}
</AccordionDetails>
</Accordion>
</List>)
})
}
</div>
</div>
)
}
const mapStateToProps = (state) => ({
user: state.user
})
const mapDispatchToProps = {}
export default connect(mapStateToProps, mapDispatchToProps)(VendorCategory)
the problem is the accordion is re-rendered every time I add an item to it and then it collapses. how do I stop it from collapsing due to re-render?UseCallback hook also re-renders. how do i use React.Memo to avoid this? Or how do I use useEffect in such a case. Again, I need to add an item without the accordion collapsing. is it possible? Any help will be appreciated.
As per the comments, mapped React elements should be given unique, stable keys that persist throughout the lifespan of the element. When a key changes, as far as React is concerned then a new component has been mounted.
Functions called inline on an element or component like key={uuid()}
or onClick={handleClick()}
will be called on every render. In this case, calling uuid()
inline was generating a new key for every render of the parent component, causing the mapped child components to be remounted.