反应上下文状态属性未定义

时间:2018-06-28 21:45:59

标签: javascript reactjs

我正在尝试使用react的新上下文API,json作为数据,Providers,Consumers等动态构建Web应用程序菜单。我不知道出现错误。但是首先这是一些代码:

上下文文件包括:

import React from 'react';
import {v1 as uuid} from 'uuid';

import MenuProvider, {MenuContext} from './contexts/menu';

import MenuDropdown from './parts/menu-dropdown';
import MenuItem from './parts/menu-item';

export default class SideMenu extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <header>
        <MenuProvider>
          <MenuContext.Consumer>
            {({state}) => (
              <React.Fragment>
                <div className="cnt-menu-head">
                  <h6>{state.menu.heading}</h6>
                </div>
                <div className="cnt-menu">
                  <ul className="nav nav-pills flex-column">
                    {state.menu.sections.map((section, i) => {
                      if (section.type === 'link') {
                        return <MenuItem exact={section.exact} linkTo={section.linkTo} linkText={section.linkText}/>
                      } else if (section.type === 'dropdown') {
                        var keyedLinks = section.links.map((link) => {
                          link.key = uuid();
                          return link;
                        });
                        return <MenuDropdown key={uuid} linkText={section.linkText} links={keyedLinks}/>
                      }
                    })}
                  </ul>
                </div>
              </React.Fragment>
            )}
          </MenuContext.Consumer>
        </MenuProvider>
      </header>
    );
  };
};

菜单组件按如下方式使用此上下文:

{
  "heading": "Menu Heading",
  "sections": [
    {
      "type": "link",
      "linkText": "A Link",
      "linkTo": "/",
      "exact": true
    },
    {
      "type": "dropdown",
      "linkText": "System",
      "links": [
        {
          "linkText": "System Table",
          "linkTo": "/table/system",
          "exact": false
        },
        {
          "linkText": "Add System",
          "linkTo": "/form/addsystem",
          "exact": false
        }
      ]
    }
  ]
}

menu.json文件包含以下数据:

"devDependencies": {
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-preset-es2016": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-router-dom": "^4.3.1",
    "uuid": "^3.3.0"
},

我在package.json中使用的软件包版本为:

.babelrc

{ "presets": [ ["es2016"], "react" ], "plugins": [ "transform-class-properties" ] } 文件是:

state.menu.sections

此应用程序的编译运行没有错误,尽管我在运行该应用程序时在控制台中遇到了javascript错误:

  

未捕获的TypeError:无法读取未定义的属性“ map”

这里要讨论的属性是state.menu.sections,我想遍历并根据类型进行渲染。 如果我注释掉用地图循环<h6>{state.menu.heading}</h6>的部分,则部分<h6>Menu Heading</h6>可以正常工作并呈现{{1}}且没有任何错误。当我循环sections数组时可能是什么问题?

1 个答案:

答案 0 :(得分:3)

尝试以下代码:

import React from 'react';

export const MenuContext = React.createContext();

class MenuProvider extends React.Component {
  state = {
    menu: { heading: '', sections: [] }
  };
  actions = {
    fetchMenu: async() => {
      const response = await fetch('/admin/json/menu.json');
      const body = await response.json();
      this.setState({
        menu: body
      });
    }
  }
  componentDidMount() {
    this.actions.fetchMenu();
  }
  render() {
    return(
      <MenuContext.Provider value={{state: this.state, actions: this.actions}}>
        {this.props.children}
      </MenuContext.Provider>
    )
  }
}

export default MenuProvider;

区别是menu中的state,而不是空的menu对象,您需要为其提供默认值。

注意:我不确定该错误,但我认为这是因为javascript尝试在map设置state.menu.sections的新状态之前在componentDidMount上使用state (因此state.menu.sections默认为undefined