Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 存储区的React/Redux props属性未定义_Javascript_Reactjs_Redux - Fatal编程技术网

Javascript 存储区的React/Redux props属性未定义

Javascript 存储区的React/Redux props属性未定义,javascript,reactjs,redux,Javascript,Reactjs,Redux,在我的应用程序中,我正在使用: "devDependencies": { "babel-plugin-transform-class-properties": "^6.24.1", "babel-preset-es2016": "^6.24.1", "babel-preset-react": "^6.24.1", "bootstrap": "^4.0.0", "browser-sync": "^2.24.5", "browser-sync-webp

在我的应用程序中,我正在使用:

"devDependencies": {
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-preset-es2016": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "bootstrap": "^4.0.0",
    "browser-sync": "^2.24.5",
    "browser-sync-webpack-plugin": "^2.2.2",
    "cross-env": "^5.1",
    "jquery": "^3.2",
    "laravel-mix": "^2.0",
    "popper.js": "^1.12",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-redux": "^5.0.7",
    "react-router-dom": "^4.3.1",
    "redux": "^4.0.0",
    "redux-thunk": "^2.3.0",
    "uuid": "^3.3.2"
},
在redux端,我有以下设置: store.js:

import {createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';

import rootReducer from './reducers';
const initialState = {};
const middleware = [thunk];

const store = createStore(rootReducer, initialState, applyMiddleware(...middleware));

export default store;
rootReducer是:

import {combineReducers} from 'redux';

import menuReducer from './menuReducer';

const rootReducer = combineReducers({
  menu: menuReducer
});

export default rootReducer;
只有menuReducer可供使用:

import * as types from '../actions/types';

const initialState = {
  data: {}
}

export default function(state = initialState, action) {
  switch (action.type) {
    case types.GET_MENU:
      return {
        ...state,
        data: action.payload
      }
    default:
      return state;
  }
}
从单个菜单操作获取其提要:

import * as types from './types';

export const getMenu = () => (dispatch) => {
  fetch('/admin/json/menu.json')
  .then(res => res.json())
  .then(data => dispatch({
      type: types.GET_MENU,
      payload: data
    })
  )
}
最后,在组件方面,我有: App.js:

从“React”导入React;
从'react redux'导入{Provider};
从“react router dom”导入{BrowserRouter};
从“../store”导入存储;
从“./SideMenu”导入侧菜单;
从“./Content”导入内容;
类应用程序扩展了React.Component{
render(){
返回(
);
};
};
导出默认应用程序;
以及尝试使用此基本redux实现的组件:

import React, {Fragment} from 'react';
import {v1 as uuid} from 'uuid';
import {connect} from 'react-redux';

import {getMenu} from '../actions/menuActions';
import MenuDropdown from './parts/menu-dropdown';
import MenuItem from './parts/menu-item';

class SideMenu extends React.Component {
  componentWillMount() {
    this.props.getMenu();
  }
  render() {
    console.log(this.props.menuData);
    return(
      <header>
        <div className="cnt-menu-head">
          <h6>{this.props.menuData.heading}</h6>
        </div>
        <div className="cnt-menu">
          <ul className="nav nav-pills flex-column">
            {this.props.menuData.sections.map((section, i) => {
              if (section.type === 'link') {
                let key = uuid();
                return <MenuItem key={key} exact={section.exact} linkTo={section.linkTo} linkText={section.linkText}/>
              } else if (section.type === 'dropdown') {
                let keyedLinks = section.links.map((link) => {
                  link.key = uuid();
                  return link;
                });
                return (
                  <Fragment key={uuid()}>
                    <div className="horizontal-separator"></div>
                    <MenuDropdown linkText={section.linkText} links={keyedLinks}/>
                  </Fragment>
                )
              }
            })}
          </ul>
        </div>
      </header>
    );
  };
};

function mapStateToProps(state) {
  return {
    menuData: state.menu.data
  }
}

export default connect(mapStateToProps, {getMenu})(SideMenu);
import React,{Fragment}来自'React';
从“uuid”导入{v1作为uuid};
从'react redux'导入{connect};
从“../actions/menuActions”导入{getMenu};
从“./parts/菜单下拉列表”导入菜单下拉列表;
从“./parts/菜单项”导入菜单项;
类侧菜单扩展了React.Component{
组件willmount(){
this.props.getMenu();
}
render(){
console.log(this.props.menuData);
返回(
{this.props.menuData.heading}
    {this.props.menuData.sections.map((section,i)=>{ 如果(section.type==='link'){ 让key=uuid(); 返回 }else if(section.type==='dropdown'){ 让keyedLinks=section.links.map((link)=>{ link.key=uuid(); 返回链接; }); 返回( ) } })}
); }; }; 函数MapStateTops(状态){ 返回{ 菜单数据:state.menu.data } } 导出默认连接(mapStateToProps,{getMenu})(侧菜单);
发生的事情是:

我得到一个错误:

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

参考
this.props.menuData.sections.map()
我的代码的一部分。有趣的是:

  • 此组件的render函数将被调用两次
  • 当我将
    console.log()
    放在action和reducer中时,我发现它们也被调用了两次
  • 当我注释掉在
    render()
    中尝试使用
    this.props.menuData
    的代码时,然后是
    console.log(this.props.menuData)在第一次运行
    render()
    时打印为空,然后在第二次运行时填充我试图使用的实际数据。我完全不知道这段代码是怎么回事,或者根本原因是什么。非常感谢您的帮助。谢谢

  • 当然,第一次渲染时没有数据。有两种方法可以解决此问题: 1.将sections键置于menuReducer的初始状态。
    2.在此.props.menuData.sections.map(…)之前添加检测。可能是这样的:this.props.menuData.sections&&this.props.menuData.sections.map(…)

    这里的问题是,您正在调用一个“异步”操作(fetch),该操作在获取数据后调度数据

    因此,您的组件将加载,但当您的函数(getMenu)将操作分派到Redux时,您的组件将第二次运行

    我可能建议进行三元测试,以调节menuData使用者的渲染并显示加载程序:

    在渲染内部:

    return this.props.menuData.sections ? (actualCodeGoesHere) : <Loader />
    
    是否返回this.props.menuData.sections?(实际情况):
    
    感谢您的明确解释。你能解释为什么方法的多重调用吗?当我把
    console.log
    放在不同的地方时,我得到了一系列冗余调用:Menu reducer、Menu reducer、Menu action、Running render、Menu reducer、Running renderFirst,我建议使用
    componentDidMount
    而不是
    componentWillMount
    ,第二个现在已经被弃用。尝试这样做,并在其中放置一个
    控制台。log
    以测试是否被调用两次,如果是,则与组件或减速机无关,它必须是其他东西,可能是路由器,让我知道
    console.log是否在
    componentDidMount
    中触发两次,我在
    componentWillMount
    中得到一个log,并且
    componentDidMount
    也有一个,但是
    render
    有两个。我猜你是对的
    BrowserRouter
    可能会在呈现定义了路由的
    内容之后重新呈现
    侧菜单
    组件。因为我得到…,运行路由器,菜单将挂载,菜单动作,运行渲染,运行内容,菜单确实挂载,菜单缩减器,运行渲染为了避免覆盖动作,您可以从应用程序组件内部调用它。多亏了Redux,这不应该是个问题,它只会填充侧菜单,或者添加一个标志来阻止未来的呼叫,希望这是有帮助的,祝你好运!
    return this.props.menuData.sections ? (actualCodeGoesHere) : <Loader />