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



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

"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;

其中只有菜单减速器在处置:

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:

import React from 'react';
import {Provider} from 'react-redux';
import {BrowserRouter} from 'react-router-dom';
import store from '../store';
import SideMenu from './sidemenu';
import Content from './content';
class App extends React.Component {
render() {
return(
<Provider store={store}>
<BrowserRouter basename='/yonetim'>
<div className="h-100">
<SideMenu className="h-100"/>
<Content className="h-100"/>
</div>
</BrowserRouter>
</Provider>
);
};
};
export default App;

以及尝试使用此基本 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);

发生的情况是:

我收到错误:

捕获的类型错误:无法读取未定义的属性"映射">

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

  1. 此组件的渲染函数被调用两次
  2. 当我在动作和减速器中都console.log()时,我看到它们也被调用了两次。
  3. 当我注释掉尝试在render()中使用this.props.menuData的代码时,渲染函数开始时console.log(this.props.menuData);在第一次运行render()中打印为空,然后填充我尝试在第二次运行中使用的实际数据。我完全不知道这段代码是怎么回事,或者根本原因是什么。任何帮助都非常感谢。谢谢。

这里的问题是你正在调用一个"异步"操作(fetch(,它在获取后调度数据。

因此,您的组件会加载,但是当您的函数 (getMenu( 将操作调度到 Redux 时,您的组件将第二次运行。

我可能会建议做一个三元来调节menuData消费者的渲染并显示一个加载器:

在渲染中:

return this.props.menuData.sections ? (actualCodeGoesHere) : <Loader />

当然,您第一次渲染时没有数据。 有两种方法可以解决此问题: 1. 将部分键放在菜单缩减器的初始状态。 2. 在此之前添加一个检测.props.menuData.section.map(...(。也许像这样:this.props.menuData.sections && this.props.menuData.section.map(...(

最新更新