Mostafa Ghadimi
Mostafa Ghadimi

Reputation: 6736

TypeError: Cannot read property 'menu_urls' of undefined

I'm trying to create a menu dynamically based on the user location in react using redux.

The makeMenu action has the following initialState in its reducer: (The whole reducer code is at the end of the post)

const initialState = {
    current_url: url,
    menu_urls:  urls.filter(item => item !== url)
}

It works fine after use it and apply mapStateToProps function in the component:


const mapStateToProps = (state) => ({
  state: state.makeMenu
})

So in the component I have accessed to its value using this.props.state.makeMenu, it works fine, as well and I get the following result after console.log(urls):

{current_url: "", menu_urls: Array(4)}
current_url: ""
menu_urls: Array(4)
0: "edu"
1: "projects"
2: "skills"
3: "honors"
length: 4
__proto__: Array(0)
__proto__: Object

The problem is when I want to map the menu_urls to create sub-menu (Menu.Item in code):

import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { Breadcrumb, Menu } from 'antd';
import { HomeOutlined } from '@ant-design/icons'

import { makeMenu } from '../../redux/actions'
import './navigation-ls.css';

class NavigationLS extends Component {

    
    render() {
        const urls = this.props.state.makeMenu
        const menu = (
          <Menu>
            {console.log(urls)}
            {
      
              urls.menu_urls.map((url) => 
                <Menu.Item>
                  <Link to={"/" + url}>
                      {url}
                  </Link>
                </Menu.Item>
              )
            }
        </Menu>
        );
        return (
          <Fragment>
              {console.log('hey')}
              {console.log(this.props.state)}
                <div className="nav">
                    <div className="pwd">
                        $PWD
                    </div>
                    <div className="breadcrumb">
                        <Breadcrumb>
                            <Breadcrumb.Item>
                                <HomeOutlined/>
                            </Breadcrumb.Item>

                            <Breadcrumb.Item overlay={menu}>
                                <Link to="/">
                                    info
                                </Link>
                            </Breadcrumb.Item>
                        </Breadcrumb>
                    </div>

                </div>
                
            </Fragment>

        )
    }
}

const mapStateToProps = (state) => ({
  state: state.makeMenu
})

export default connect(
  mapStateToProps,
  { makeMenu }
)(NavigationLS)

As I said console.log(urls) works fine but the urls.menu_urls doesn't work. I have read the similar question on stackoverflow but none of them helps.

EDIT:

makeMenu reducer:

import { MAKE_MENU } from '../actionTypes'

const urls = [
    "",
    "edu",
    "projects",
    "skills",
    "honors",
]

const url = window.location.href.split("/")[3]

const initialState = {
    current_url: url,
    menu_urls:  urls.filter(item => item !== url)
}

const makeMenu =  (state = initialState, action) =>  {
    switch(action.type) {
        case MAKE_MENU: {
            const { content } = action.payload
            return {
                current_url: content,
                menu_urls: urls.filter(item => item !== content)
            }
        }
        default:
            return state
    }
}

export default makeMenu

Upvotes: 0

Views: 84

Answers (1)

Alireza Fa
Alireza Fa

Reputation: 141

You are setting urls to this.props.state.makeMenu while it is undefined. You should set urls to this.props.state.

Upvotes: 1

Related Questions