Jud3v Digital
Jud3v Digital

Reputation: 311

categories and sub categories in ReactJS

Hello I'm trying to make a sidebar menu using material ui

This sidebar menu contain categories and there sub categories.

I have code this:

What I'm trying to make ?

I take some categories data from my Laravel API, on each categories they can have an object of sub categories, and I collapse this to show the sub categories from the parent category

If I collapse one every one collapse, this is normal because they share the same state, but I don't know how to make one state for each parent categories

const categoriesList = this.state.categories.map((item, k) => {
            return (
                <React.Fragment key={k}>
                    <ListItem button onClick={this.handleClick}>
                        <ListItemText primary={item.label} />
                        {item.category !== null ? this.state.open ? <ExpandLess /> : <ExpandMore /> : null}
                    </ListItem>
                    {item.category !== null ? <>
                        <Collapse in={this.state.open} timeout="auto" unmountOnExit>
                            <List component="div" disablePadding>
                                {item.category.map((ite,l) => <ListItem key={l} button className={classes.nested}><ListItemText primary={ite.label} /></ListItem>)}
                            </List>
                        </Collapse>
                    </> : null}
                </React.Fragment>
            )
        })
``

Upvotes: 0

Views: 4336

Answers (2)

Jud3v Digital
Jud3v Digital

Reputation: 311

This is my parent component with hook

first time I use hooks

import React, {useState} from 'react';
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import ExpandLess from "@material-ui/icons/ExpandLess";
import ExpandMore from "@material-ui/icons/ExpandMore";
import Collapse from "@material-ui/core/Collapse";
import List from "@material-ui/core/List";


export function Category(props){
    const [open, setOpen] = useState(false);
    let handleClick = () => {
        setOpen(!open)
    }
    return (
        <React.Fragment key={props.id}>
            <ListItem button onClick={handleClick}>
                <ListItemText primary={props.categorie.label} />
                {props.category !== null ? open ? <ExpandLess /> : <ExpandMore /> : null}
            </ListItem>
            {props.category !== null ? <>
                <Collapse in={open} timeout="auto" unmountOnExit>
                    <List component="div" disablePadding>
                        {props.category.map((ite,l) => <ListItem key={l} button className={props.classes.nested}><ListItemText primary={ite.label} /></ListItem>)}
                    </List>
                </Collapse>
            </> : null}
        </React.Fragment>
    )
}

Upvotes: 0

idbentley
idbentley

Reputation: 4218

I would recommend that you create a component for each category. So instead you would have:

const categoriesList = this.state.categories.map((item, k) => {
    return <Category key={k} {...item} />;
});

And elsewhere in your code you'd have another Component:

const Category = (props) => {
    const [open, setOpen] = useState(false);
    function handleClick(e) { ... }
    return (
        <React.Fragment>
            <ListItem button onClick={handleClick}>
                <ListItemText primary={props.label} />
                    {props.category !== null ? open ? <ExpandLess /> : <ExpandMore /> : null}
                </ListItem>
                {item.category !== null ? <>
                    <Collapse in={open} timeout="auto" unmountOnExit>
                        <List component="div" disablePadding>
                            {props.category.map((ite,l) => <ListItem key={l} button className={classes.nested}><ListItemText primary={ite.label} /></ListItem>)}
                        </List>
                    </Collapse>
                </> : null}
            </React.Fragment>
    );

}

Then the state is contained with the Category component, and you can keep your container component simple.

[note] I prefer function components, so used that here, but a Class Component wouldn't change this answer.

Upvotes: 2

Related Questions