React Router v4 集成 redux 后不加载组件

React Router v4 doesn't load component after integrating redux

我是一个 React 和 Redux 初学者。我创建了一个没有 redux 的 React 应用程序并集成了 React Router v4。一切都很完美。

然后我将 redux 集成到应用程序中,这样我就可以共享状态。在此之后我的路由器停止工作。所以我想解决这个问题我应该集成 react-router-redux v5 (我实际上了解到你不必添加 react-router-redux 来使路由器工作。它在那里更新关于路由器信息的 redux 状态)。路由器仍然无法正常工作。

当我点击应该加载路由器的 link 时,浏览器 url 更改为正确的路由器 url 并且 redux 路由器状态更改为正确的路由器(使用 react dev 观察到这一点工具)。如果我刷新页面,将加载与路由器相关的组件。

我配置的 redux store 文件

/**
 * Created by Shane on 5/12/2017.
 */
import { createStore,combineReducers,applyMiddleware,compose } from 'redux'
import {authenticationReducer} from './../reducers/index'
import { reducer as formReducer } from 'redux-form'
import thunk from   'redux-thunk'
import {  routerReducer, routerMiddleware } from 'react-router-redux'
import createHistory from 'history/createBrowserHistory'


// Create a history of your choosing (we're using a browser history in this case)
 const history = createHistory();

 let configureStore = () => {

    const persistedState = localStorage.getItem('reduxState') ? JSON.parse(localStorage.getItem('reduxState')) : {};

    let reducer=combineReducers({
        authenticationData:authenticationReducer,
        router:routerReducer,
        form: formReducer     // <---- Mounted at 'form'
    });


//creating the store using reducer
    let store=createStore(reducer,
        persistedState,
        compose(applyMiddleware(thunk,routerMiddleware(history)),
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()));

    store.subscribe(() => {
        // console.log("Current State",store.getState());
        localStorage.setItem('reduxState', JSON.stringify(store.getState()))
    });



    return store;
};

module.exports ={
    history,
    configureStore
};

这是我的主文件

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom'
import {Provider} from 'react-redux'
import Base from './base/Base';
import 'mdi/css/materialdesignicons.css'
import './index.css';
import * as storeConfig from './redux/store/store'
import { ConnectedRouter } from 'react-router-redux'
import createHistory from 'history/createBrowserHistory'


let store=storeConfig.configureStore();
const history = storeConfig.history;

ReactDOM.render(

    <Provider store={store}>
        <ConnectedRouter history={history}>
                <Base />
        </ConnectedRouter>
    </Provider>,
  document.getElementById('root')
);

我定义路由的基础文件

import  React  from 'react';
import { Grid } from 'react-bootstrap';
import { Row } from 'react-bootstrap';
import { Col } from 'react-bootstrap';
import {connect} from 'react-redux'
import Content from '../Content';
import AppNavBar from '../nav_bar/app_nav_bar/AppNavBar';
import './Base.css';
import Login from "../login/Login";
import Profile from "../profile/Profile";
import MyApps from "../my_apps/MyApps";
import NewAppBase from "../new_app/new_app_base/NewAppBase";
import {Route} from "react-router";


class Base extends React.Component {


    constructor(props) {
        super(props);
        // this.state = { isLogged: true } ;
    }


  render() {

      //let {dispatch} =this.props;
      let  content=(<div></div>);

   //   dispatch(action.apiLogIn("y2kshane","Abcd1234"));
        if(this.props.isLogged)
        {
          content=(
              <Grid className="Parent-container">
                  <Row>
                      <Col xs={12} md={12}>  <AppNavBar/></Col>
                  </Row>

                  <Row >
                      <Col xs={12} md={12} className="content">
                          {/*<Content/>*/}

                          <Route exact path='/profile' component={Profile}/>
                          <Route exact path='/my-apps' component={MyApps}/>
                          <Route exact path='/new-app' component={NewAppBase}/>


                      </Col>

                  </Row>


              </Grid>
             );
        }else {
            content=(<Login/>);
        }



    return (
       <span>{content}</span>
    );


  }

}

export default connect((state) => {
    return {
        isLogged:state.authenticationData.isLogged
    }
})(Base);

我调用路由的 AppNavBar 文件

/**
 * Created by admin on 4/27/2017.
 */
import React, { Component } from 'react';
import { Navbar } from 'react-bootstrap';
import { Nav } from 'react-bootstrap';
import { NavItem,NavDropdown,MenuItem } from 'react-bootstrap';
import './AppNavBar.css';
import {connect} from "react-redux";
import * as action from './../../redux/actions/index'
import {push} from "react-router-redux";


class AppNavBar extends Component {

    constructor(props) {
        super(props);
        // this.state = { isLogged: true } ;
      //  this.navigateTo.bind(this);
    }

    logout = () => {

        console.log("calling logot");
        this.props.dispatch(action.logoutAction())
    };

    navigateTo = (url) =>
    {
        this.props.dispatch(push(url))
    };


    render() {
        return (
            <Navbar className="nav-bar" collapseOnSelect>
                <Navbar.Header >
                    <Navbar.Brand className="nav-bar-text">
                        <a href="#">Dev Dashboard</a>
                    </Navbar.Brand>
                    <Navbar.Toggle />
                </Navbar.Header>
                <Navbar.Collapse>
                    <Nav>
                        {/*<LinkContainer to="/profile">*/}
                            <NavItem eventKey={1} onClick={() => this.navigateTo("/profile")}>Profile</NavItem>
                        {/*</LinkContainer>*/}
                        {/*<LinkContainer to="/my-apps">*/}
                            <NavItem eventKey={2} onClick={() => this.navigateTo("/my-apps")}>My Apps</NavItem>
                        {/*</LinkContainer>*/}
                        <NavItem eventKey={2} href="#" className="nav-bar-text">Reports</NavItem>
                        <NavItem eventKey={2} href="#" className="nav-bar-text">API Browser</NavItem>
                        <NavItem eventKey={2} href="#" className="nav-bar-text">Knowledge Base</NavItem>
                    </Nav>
                    <Nav pullRight>
                        <NavDropdown eventKey={3} title={this.props.username} id="basic-nav-dropdown">
                            {/*<NavBarUser/>*/}
                            <MenuItem eventKey={3.1}>Settings</MenuItem>
                            {/*<MenuItem eventKey={3.2}>Another action</MenuItem>*/}
                            {/*<MenuItem eventKey={3.3}>Something else here</MenuItem>*/}
                            <MenuItem divider />
                            <MenuItem eventKey={3.3} onClick={this.logout} ><b>Logout</b></MenuItem>
                        </NavDropdown>


                    </Nav>
                </Navbar.Collapse>
            </Navbar>

        );
    }
}


export default connect(
    (state) => {
        return {
            username : state.authenticationData.userName
        }
    }
)(AppNavBar);

我已经尝试修复此问题大约 2 天了:( 。请帮助我。谢谢。

所以事实证明,您必须使用 withRouter 包装具有路由的组件。我认为这是与 redux connect 相关的一些问题。

export default withRouter(connect((state) => {
   return {
       isLogged:state.authenticationData.isLogged
   }
})(Base));

完整代码

import  React  from 'react';
import { Grid } from 'react-bootstrap';
import { Row } from 'react-bootstrap';
import { Col } from 'react-bootstrap';
import {connect} from 'react-redux'
import Content from '../Content';
import AppNavBar from '../nav_bar/app_nav_bar/AppNavBar';
import './Base.css';
import Login from "../login/Login";
import Profile from "../profile/Profile";
import MyApps from "../my_apps/MyApps";
import NewAppBase from "../new_app/new_app_base/NewAppBase";
import {Route, withRouter} from "react-router-dom";


class Base extends React.Component {


    constructor(props) {
        super(props);
        // this.state = { isLogged: true } ;
    }


  render() {

      //let {dispatch} =this.props;
      let  content=(<div></div>);

   //   dispatch(action.apiLogIn("y2kshane","Abcd1234"));
        if(this.props.isLogged)
        {
          content=(
              <Grid className="Parent-container">
                  <Row>
                      <Col xs={12} md={12}>  <AppNavBar/></Col>
                  </Row>

                  <Row >
                      <Col xs={12} md={12} className="content">
                          {/*<Content/>*/}

                          <Route exact path='/profile' component={Profile}/>
                          <Route exact path='/my-apps' component={MyApps}/>
                          <Route exact path='/new-app' component={NewAppBase}/>


                      </Col>

                  </Row>


              </Grid>
             );
        }else {
            content=(<Login/>);
        }



    return (
       <span>{content}</span>
    );


  }

}

export default withRouter(connect((state) => {
    return {
        isLogged:state.authenticationData.isLogged
    }
})(Base));