我正在使用redux和react-router(也使用react-router-redux)开发我的第一个反应应用程序。我想要一种方式来呈现两种不同的布局;用户未登录时的一个布局和用户登录时的另一个布局。
我想知道如何在我的代码中解决这个问题,或者如何达到预期的结果。
以下是我的尝试:
创建根组件App.js,该组件从商店的状态读取值以了解用户是否已登录。
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
//Import Components
import Main from '../components/Main'
//Import necessary actions
import * as loginActions_ from '../actions/login'
const mapStateToProps = (state) => {
return {
loginStatus: state.loginStatus
}
}
const mapDispatchToProps = (dispatch) => {
const loginActions = bindActionCreators (loginActions_, dispatch)
return {
loginActions
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Main)
创建了一个演示文稿(Main.js)组件,该组件使用loginStatus呈现适当的布局。
import React, { Component } from 'react'
import { Container } from 'semantic-ui-react'
import MainLayoutOut from './MainLayoutOut'
import MainLayoutIn from './MainLayoutIn'
export default class Main extends Component {
constructor(props){
super(props)
}
render(){
const child = (this.props.loginStatus? <MainLayoutIn loginStatus={this.props.loginStatus} loginActions={this.props.loginActions} />
: <MainLayoutOut loginStatus={this.props.loginStatus} loginActions= {this.props.loginActions} /> )
return(
<Container>
{child}
</Container>
)
}
}
MainLayoutOut.js呈现它自己的菜单,内容(子项)和页脚。
import React, {Component} from 'react'
import {Container, Segment } from 'semantic-ui-react'
import Footer from './Footer'
import MenuOut from './MenuOut'
export default class MainLayoutOut extends Component {
constructor(props){
super(props)
}
render(){
return(
<Container fluid>
<MenuOut/>
<Segment key='contentOut'>
{React.cloneElement(this.props.children, this.props)}
</Segment>
<Footer/>
</Container>
)
}
}
同样,MainLayoutIn.js具有以下结构:
import React, {Component} from 'react'
import {Container, Segment, Header} from 'semantic-ui-react'
export default class MainLayoutIn extends Component {
constructor(props){
super(props)
}
render(){
return(
<Container>
<Segment key='menuIn'>Header In</Segment>
<Segment key='contentIn'>
<Header as='h1'>Content In</Header>
{/*this.props.children*/}
</Segment>
<Segment key='footerIn'>FooterIn</Segment>
</Container>
)
}
}
以下是我创建商店的方式。
import { applyMiddleware, createStore } from 'redux'
import createLogger from 'redux-logger'
import ReduxThunk from 'redux-thunk'
import initialState from '../initialState'
import rootReducer from '../reducers'
const logger = createLogger()
const middlewares = [ReduxThunk, logger]
export default function configureStore(initialStateParam = initialState){
return createStore(rootReducer, {}, applyMiddleware(...middlewares));
}
减少根减速器;减速器/ index.js
import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux'
import loginStatus from './loginStatus'
const rootReducer = combineReducers({
routing: routerReducer,
loginStatus
})
export default rootReducer
现在的loginStatus reducer就像:
export default function loginStatus(state = false, action){
console.log('Login Status fired!')
return state
}
最后是设置应用程序的client.js文件。
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { syncHistoryWithStore } from 'react-router-redux'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import configureStore from '../src/store/configureStore'
import App from '../src/containers/App'
import Main from '../src/components/Main'
import MainLayoutIn from '../src/components/MainLayoutIn'
import MainLayoutOut from '../src/components/MainLayoutOut'
import Blog from '../src/components/Blog'
import SignUp from '../src/components/SignUp'
import Login from '../src/components/Login'
const store = configureStore()
const history = syncHistoryWithStore(browserHistory, store)
const router = (
<Provider store={store}>
<Router history={history}>
<Route path='/' component={App}>
<Route path='/' component={Main}>
<Route path='/' component={MainLayoutOut}>
<IndexRoute component={Blog}></IndexRoute>
<Route path='/login' component={Login}/>
<Route path='/signup' component={SignUp}/>
</Route>
<Route path='/' component={MainLayoutIn}>
</Route>
</Route>
</Route>
</Router>
</Provider>
)
render( router ,document.getElementById('app'))
client.js文件用于路由应用程序的组件。我希望当用户登录时,他应该登陆页面(目的MainLayoutOut.js),该页面具有菜单(具有访问博客列表,注册和登录的菜单项)的内容和页脚。但是当用户进行身份验证并获得授权时,他可能会看到完全不同的布局(MainLayoutIn.js的用途)以及自己的菜单,内容和页脚。
运行上面的代码会产生错误消息:
Uncaught TypeError: Cannot read property 'props' of undefined
at Object.ReactElement.cloneElement (http://localhost:3000/bundle.js:6362:35)
at Object.cloneElement (http://localhost:3000/bundle.js:23625:49)
at MainLayoutOut.render (http://localhost:3000/bundle.js:17164:28)
at MainLayoutOut.tryRender (http://localhost:3000/bundle.js:3912:32)
at MainLayoutOut.proxiedMethod (http://localhost:3000/bundle.js:52020:31)
at http://localhost:3000/bundle.js:44855:22
at measureLifeCyclePerf (http://localhost:3000/bundle.js:44134:13)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (http://localhost:3000/bundle.js:44854:26)
at ReactCompositeComponentWrapper._renderValidatedComponent (http://localhost:3000/bundle.js:44881:33)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3000/bundle.js:44421:31)