0

I'm trying to bind the data to the MenuItems at the nested menu level. I can successfully map the data to populate the main levels, but the submenus are giving me an error.

My JSON looks like this:

const languages = [
    {
        name: 'English',
        icon: './assets/images/flags/uk.png',
        link: ''
    },
    {
        name: 'Español',
        icon: './assets/images/flags/Spain.png',
        link: ''
    },
    {
        name: 'Français',
        icon: './assets/images/flags/France.png',
        link: ''
    }
];

I am saving the submenu in a const so I can use it in the render. (I believe this is my problem area but not sure what I need to do)

class Menu extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            show: false,
            open: false
        }
    }
    render() {
        const { colorOption } = this.props;

        //the code inside this const will work if I insert it inside my IconMenu. But it doesn't work inside the menuItems property which should be able to hold MenuItem objects    
        const languageMenu = {languages.map((item, index) => (
            <MenuItem
                key={index}
                className={classnames('menu-item', {
                    'bg-color-medlight': ['11', '12', '13', '14', '15', '16'].indexOf(colorOption) >= 0,
                    'bg-color-meddark': ['21', '22', '23', '24', '25', '26'].indexOf(colorOption) >= 0
                })}
                primaryText={languages[index].name}
                style={{userMenuItem}}
                leftIcon={
                    <img className="flag" src={languages[index].icon}/>
                }/>
        ))}

        return(
        <div style={{zIndex:2}}>
            <ul className="list-unstyled">
                    <li>
                        <IconMenu
                            className="user"
                            iconButtonElement={
                                <RaisedButton style={ImgIconButtonStyle}><PersonalMenuIcon/></RaisedButton>
                            }
                            onChange={this.handleChange}
                            anchorOrigin={{horizontal: 'right', vertical: 'bottom'}}
                            targetOrigin={{horizontal: 'right', vertical: 'top'}}>

                            <MenuItem
                                className={classnames('menu-item', {
                                    'bg-color-medlight': ['11', '12', '13', '14', '15', '16'].indexOf(colorOption) >= 0,
                                    'bg-color-meddark': ['21', '22', '23', '24', '25', '26'].indexOf(colorOption) >= 0
                                })}
                                primaryText="English"
                                rightIcon={<ArrowDropRight />}
                                style={{userMenuItem}}
                                leftIcon={
                                    <img className="flag" src="./assets/images/flags/uk.png"/>
                                }
                                menuItems={{languageMenu}}
                                />
                        </IconMenu>
                    </li>
                </ul>
            </div>
        );
    } 

}

In a perfect world, a regular nested menu looks like this:

import React from 'react';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import IconButton from 'material-ui/IconButton';
import Divider from 'material-ui/Divider';
import Download from 'material-ui/svg-icons/file/file-download';
import ArrowDropRight from 'material-ui/svg-icons/navigation-arrow-drop-right';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';

/**
 * Example of nested menus within an IconMenu.
 */
const IconMenuExampleNested = () => (
  <IconMenu
    iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
    anchorOrigin={{horizontal: 'left', vertical: 'top'}}
    targetOrigin={{horizontal: 'left', vertical: 'top'}}
  >
    <MenuItem
      primaryText="Copy & Paste"
      rightIcon={<ArrowDropRight />}
      menuItems={[
        <MenuItem primaryText="Cut" />,
        <MenuItem primaryText="Copy" />,
        <Divider />,
        <MenuItem primaryText="Paste" />,
      ]}
    />

    <MenuItem
      primaryText="Case Tools"
      rightIcon={<ArrowDropRight />}
      menuItems={[
        <MenuItem primaryText="UPPERCASE" />,
        <MenuItem primaryText="lowercase" />,
        <MenuItem primaryText="CamelCase" />,
        <MenuItem primaryText="Propercase" />,
      ]}
    />

  </IconMenu>
);

export default IconMenuExampleNested;

And the error I am getting is

Module build failed: SyntaxError: C:/xampp/htdocs/ScalaCMReact/src/components/Header/UserMenu.js: Unexpected token, expected , (109:33)

107 |       const { colorOption } = this.props;
108 | 
109 |       const languageMenu = {languages.map((item, index) => (
    |                                      ^
110 |           <MenuItem
111 |               key={index}
112 |               className={classnames('menu-item', {

@ ./src/components/Header/index.js 23:16-37
@ ./src/routes/app/components/MainApp.js
@ ./src/routes/app/index.js
@ ./src/client.js
@ multi (webpack)-dev-server/client?http://localhost:8000 webpack/hot/dev-server webpack-dev-server/client?http://0.0.0.0:8000/ webpack/hot/only-dev-server react-hot-loader/patch ./client.js

What am I doing wrong?

Thanks in advance

1 Answer 1

1

Doesn't seems like valid javascript

const languageMenu = {languages.map((item, index) => (
            <MenuItem
                key={index}
                className={classnames('menu-item', {
                    'bg-color-medlight': ['11', '12', '13', '14', '15', '16'].indexOf(colorOption) >= 0,
                    'bg-color-meddark': ['21', '22', '23', '24', '25', '26'].indexOf(colorOption) >= 0
                })}
                primaryText={languages[index].name}
                style={{userMenuItem}}
                leftIcon={
                    <img className="flag" src={languages[index].icon}/>
                }/>
        ))}

If you are trying to create an array of arrays then the outer brackets should be []. If it's an object which has a property which contains the array of MenuItem's then

const languageMenu = {languages: languages.map((item, index) => (
            <MenuItem
                key={index}
                className={classnames('menu-item', {
                    'bg-color-medlight': ['11', '12', '13', '14', '15', '16'].indexOf(colorOption) >= 0,
                    'bg-color-meddark': ['21', '22', '23', '24', '25', '26'].indexOf(colorOption) >= 0
                })}
                primaryText={languages[index].name}
                style={{userMenuItem}}
                leftIcon={
                    <img className="flag" src={languages[index].icon}/>
                }/>
        ))}

If you want to set the languageMenu to a react element then

const languageMenu = <div>
{languages.map((item, index) => (
            <MenuItem
                key={index}
                className={classnames('menu-item', {
                    'bg-color-medlight': ['11', '12', '13', '14', '15', '16'].indexOf(colorOption) >= 0,
                    'bg-color-meddark': ['21', '22', '23', '24', '25', '26'].indexOf(colorOption) >= 0
                })}
                primaryText={languages[index].name}
                style={{userMenuItem}}
                leftIcon={
                    <img className="flag" src={languages[index].icon}/>
                }/>
        ))}
</div>
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you Mukesh, That fixed the initial error but the error I'm getting now says Failed prop type: Invalid prop "menuItems" supplied to "MenuItem", expected a ReactNode. and when I click on the menu I get one more error that says Uncaught Error: Objects are not valid as a React child (found: object with keys {languageMenu}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of "MenuItem".
This is very related to what you were saying, but I tried injecting inside [ ] and kept getting errors
That's because menuItem props is expecting a react node and you are sending it an object which it tries to render. I don't know the Material UI library works. But you probably want to wrap the array of submenus in a div
I have added another option for languageMenu, which should take care of the error. But i don't know if it will give the output you want
Wrapping a div around them didn't do anything either. I can't manually input these. Well, I could, but I need to have them in a json so I can manipulate them better. The chosen language will be shown on other elements and eventually translate the app.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.