user12356906
user12356906

Reputation:

Reactjs Jsx Conditional and useState logic

I'm trying to do the following I have a dropdown menu where I created state to have only one menu item active at a time and I will also use this to make the active page effect And then I need to do this check on my jsx I move to my menu in all my states I need to check the following:

const { name, link, dropdownItems } = tag;

if my name exists in my visibleMenu array and if it is true and I also need to check if my dropdownItems is true for there yes render my dropdown menu, basically i'm a little confused on how to do these checks in jsx

code:

const MenuBar = props => {
  const MenuTags = [
    {
      name: 'home',
      link: '/',
      dropdownItems: {
        names: ['one', 'two', 'three'],
        link: ['/aa', '/b'],
      },
    },
    {
      name: 'about',
      link: '../abovisibleMenuut',
      dropdownItems: {
        names: ['one', 'two', 'three'],
        link: ['/aa', '/b'],
      },
    },
    { name: 'not dropdown', link: '../dashboard' },
    { name: 'not dropdown', link: '../dashboard/about' },
  ];
  const [visibleMenu, setVisibleMenu] = useState(
      MenuTags.reduce((r, e) => ((r[e.name] = false), r), {}),
    ),
    onUpdateVisibility = item => {
      const visibleMenuCopy = { ...visibleMenu };
      Object.keys(visibleMenuCopy).forEach(
        key => (visibleMenuCopy[key] = key === item),
      );
      setVisibleMenu(visibleMenuCopy);
    };
  console.log(visibleMenu);
  return (
      <>
      {MenuTags.map(item => (
        <MenuItem
          tag={item}
          visibleMenu={visibleMenu}
          onClick={() => onUpdateVisibility(item)}
        />
      ))}
      </>
  );
};

and this is my menu items: ( here i need jsx conditions )

const MenuItem = ({ tag, visibleMenu }) => {
  const { name, link, dropdownItems } = tag;
  console.log(visibleMenu);
  return (
    <NavLi>
      <Link to={link}>{name}</Link>
    </NavLi>
  );
};

I don't know if this is the correct logic, but it was the only way I managed to get only one state of my array to be true at a time to render my dropdown menu or apply a css to my active item

Upvotes: 0

Views: 56

Answers (1)

Alex Dunlop
Alex Dunlop

Reputation: 1606

Hey I answered you other question didn't know you only wanted one visible menu but, I'll use the code I had yesterday, I still think you should change the way you are managing your visibleMenu. Instead of setting the visible inside the MenuItem class you can set it on the MenuBar

const MenuBar = props => {
  const menuTags = [
    { name: 'home', link: '/', dropdownItems: ['one', 'two', 'three'] },
    // ... other menu tags you had.
  ]

  const [visibleIndex, setVisibleIndex] = useState(null)

  const = handleClick = index => {
    if (visibleIndex === index) return setVisibleIndex(null)

    return setVisibleIndex(index)
  }

  return (
    <NavUl isOpen={props.isOpen}>
      {menuTags.map((menuTag, index) => {
        return (
          <MenuTag
            tag={menuTag}
            visibility={index === visibleIndex}
            onClick={() => handleClick(index)}
          />
        )
      })}
      <li>
        <FontAwesomeIcon
          // Move the logic to only be in the Parent, this component shouldn't have to
          // pass it's parents variables.
          onClick={props.toggleOpen}
          // ... the rest of what you had
        />
      </li>
    </NavUl >
  )
}
// Handle visibility through props instead!
const MenuItem = ({ tag, visibility }) => {
  const { name, link, dropdownItems } = tag;

  return (
    <NavLi >
      <Link to={link}>{name}</Link>
      // If these are true dropdown items will appear.
      {visibility && dropdownItem && (
        {dropdownItems.map(item => (
          <ul>
            <li>
              <a>{item}</a>
            </li>
          </ul>
        ))}
      )}
    </NavLi>
  );
};

Hope that helps and happy coding :)

Upvotes: 1

Related Questions