infodev
infodev

Reputation: 5235

Apply style on specific react map item

I would like to apply a class on a specific element of loop map.

const items = [
    {
        key: 'Menu1key',
        content: 'Menu 1',
    },
    {
        key: 'Menu2',
        content: 'Menu2key'
    },
    {
        key: 'Menu3Key',
        content: 'Menu3',
        children: [{
            key: 'SubMenu3Key',
            content: 'SubMenu3',

        },
        {
            key: 'SubMenu5Key',
            content: 'SubMenu5'
        }]
    },
    {
        key: 'Menu4Key',
        content: 'Meu4',
        children: [{
            key: 'SubMenu4Key',
            content: 'SubMenu4',

        },
        {
            key: 'SubMenu5Key',
            content: 'SubMenu5'
        }]
    }
]

const StackedMenu = (props) => {
    let [chevronRotation, setChevronRotation] = useState('')
    let [itemClicked, setItemClicked] = useState(props.itemClicked);
    let [depth, setDepth] = useState(props.depth)
    return (<Menu primary defaultActiveIndex={0} activeIndex={itemClicked} vertical pointing style={{ width: '100%' }}>
        {props.items.map((item, index) => {
            return (<>
                <MenuItem onClick={(e, data) => { setItemClicked(data.index); setChevronRotation(`rotate`) }} index={index} key={index} pointing="start" >
                    <Menu.ItemContent style={depth > 0 ? { paddingLeft: '0.5em' } : null} >{item.content}</Menu.ItemContent>
                    {item.children ?
                        (<Menu.ItemIcon id={index} style={{ right: "0px", position: "absolute" }} className={props.itemClicked === index && item.children ? 'rotate' : ''}>
                            <ChevronEndMediumIcon />
                        </Menu.ItemIcon>) : null}
                </MenuItem>
                {itemClicked === index && item.children ? <div><StackedMenu items={item.children} depth={depth + 1} itemClicked={0} /></div> : null}
            </>)
        })}
    </Menu>)
}

I using a recursive component to create children sub menu.

Actually when I open a menu all chevrons get expanded , what I'm looking for is that only the chevron of the clicked item get expanded.

enter image description here

Upvotes: 0

Views: 822

Answers (3)

Jayanth MKV
Jayanth MKV

Reputation: 313

using "Code Splitting". Just create a separate component and place the state inside that component. This creates a separate state for each item n the list so that the onclick obeys for that item only.

<div>
<Mycomponent />
</div>

const Mycomponent = ()=>{
    const [active, setactive] = useState(false);

return (
<div>
<div
          key={i}
          style={{
            boxShadow: active 
              ? "4px 3px 8px 0px rgba(1, 156, 48, 0.3)" 
              : "initial"
          }}
          onClick={() => setactive(!active)}
        >
          {message.content}
        </div>
<div>
);

Upvotes: 0

michael
michael

Reputation: 4173

You should use the component's state to check if menu item is opened or not. Also, I've removed unnecessary depth state. Hope this could help.

const StackedMenu = ({items, depth, ...otherProps}) => {
  let [chevronRotation, setChevronRotation] = useState('');
  let [itemClicked, setItemClicked] = useState(otherProps.itemClicked);

  return (
    <Menu
      primary
      defaultActiveIndex={0}
      activeIndex={itemClicked}
      vertical
      pointing
      style={{width: '100%'}}>
      {items.map((item, index) => {
        return (
          <>
            <MenuItem
              onClick={(e, data) => {
                setItemClicked(data.index);
                setChevronRotation(`rotate`);
              }}
              index={index}
              key={index}
              pointing="start">
              <Menu.ItemContent
                style={depth > 0 ? {paddingLeft: '0.5em'} : null}>
                {item.content}
              </Menu.ItemContent>
              {item.children ? (
                <Menu.ItemIcon
                  id={index}
                  style={{right: '0px', position: 'absolute'}}
                  className={itemClicked === index ? 'rotate' : ''}>
                  <ChevronEndMediumIcon />
                </Menu.ItemIcon>
              ) : null}
            </MenuItem>
            {itemClicked === index && item.children ? (
              <div>
                <StackedMenu
                  items={item.children}
                  depth={depth + 1}
                  itemClicked={0}
                />
              </div>
            ) : null}
          </>
        );
      })}
    </Menu>
  );
};

Upvotes: 1

Thales Kenne
Thales Kenne

Reputation: 2932

Your problem is that you're setting a local state to control whether it should be open, but then checks on the props for the clicked item.

Change this line:

// I removed props from  props.itemClicked
<Menu.ItemIcon id={index} style={{ right: "0px", position: "absolute" }} className={itemClicked === index && item.children ? 'rotate' : ''}> 

Upvotes: 1

Related Questions