如何在react.js中使用react-router的布局组件

时间:2016-12-10 05:39:47

标签: node.js reactjs react-router react-redux

我正在使用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) 

0 个答案:

没有答案