【问题标题】:Cannot make react-router 4 render routes right无法使 react-router 4 渲染路由正确
【发布时间】:2019-02-09 19:33:58
【问题描述】:

我用 react、redux 和 webpack 得到了那个简单的应用程序

// entry.js
import React from "react";
import {render} from "react-dom";
import { Provider } from "react-redux";
import { Router } from "react-router-dom";
import createHistory from 'history/createBrowserHistory'

import store from './containers/store/index';
import App from './components/App.jsx';

const history = createHistory();

render((
  <Provider store={store}>
    <Router history={history}>
      <App history={history} />
    </Router>
  </Provider>),
  document.getElementById('root')
)

如果用户未登录(userInfo 为空),那么我希望路径为 / 并呈现 Home 组件,当用户登录时,我希望路径为 /lobby 并呈现 Lobby 组件.

但是尽管浏览器中的路径发生了变化,Home 组件还是被渲染了。只有当我第二次单击它时才会呈现Lobby。我的错误是什么?

// App.js
import React, { Component } from 'react';
import {connect} from "react-redux";
import { Switch, Route } from "react-router-dom";

import Profile from "./Profile";
import Lobby from "./Lobby";
import Home from "./Home";
import Signin from "./Signin";

const mapStateToProps = state => {
  return { userInfo: state.userInfo };
};

class App extends Component {
  constructor(props) {
    super(props);
  }

  updateHistory() {
    if (!this.props.userInfo && !this.props.history.location.pathname === '/') {
      this.props.history.replace("/");
      this.setState(this.state); // to rerender
    }

    if (this.props.userInfo && this.props.history.location.pathname === '/') {
      this.props.history.replace("/lobby");
      this.setState(this.state); // to rerender
    }    
  }

  componentWillMount() {
    this.updateHistory()
  }

  componentDidUpdate(prevProps) {
    this.updateHistory()
  }

  render() {
    return (
      <Switch>
        <Route exact path='/' component={Home} />
        <Route path='/lobby' component={Lobby} />
        <Route path='/profile' component={Profile} />
        <Route path='/signin' component={Signin} />
      </Switch>
    )
  }
}

const connectedPage = connect(mapStateToProps, { })(App);

export default connectedPage;

我在Home 组件上还有一个Link,它改变了浏览器导航面板中的路径,但根本不影响渲染的Home 组件。

// Home.js
import React, { Component } from 'react';
import Header from 'semantic-ui-react/dist/es/elements/Header/Header';
import Button from 'semantic-ui-react/dist/es/elements/Button/Button';
import Container from 'semantic-ui-react/dist/es/elements/Container/Container';
import {connect} from "react-redux";
import { Link } from "react-router-dom";

import l10n from '../../l10n/ru';
import { userRegister } from '../../containers/actions';

const mapStateToProps = state => {
  return { isRegistering: state.isRegistering };
};

class Home extends Component {
  render() {
    return (
      <Container className="page-home">
        <Header as="h1" className="page-title">Home</Header>
        <div className="home-text">
          <p>{ l10n.HOME_TEXT }</p>
        </div>
        <div className="link-signin-container">
          <p>{l10n.HOME_SIGIN_TEXT} <Link to="/signin">{l10n.HOME_SIGIN_LINK}</Link></p>
        </div>
        <div className="home-button-container">
          <Button
            size="massive"
            icon="play"
            content={l10n.HOME_PLAY_BUTTON_TEXT}
            labelPosition="right"
            loading={this.props.isRegistering}
            onClick={this.props.userRegister}
          />
        </div>
      </Container>
    )
  }
}

const connectedPage = connect(mapStateToProps, { userRegister })(Home);

export default connectedPage;

我感觉好像我缺少一些关于使用 react-router 进行路由的基本知识。

【问题讨论】:

    标签: reactjs react-redux react-router


    【解决方案1】:

    尝试使用this.props.location 而不是this.props.history.location。见this part of the docs

    至于链接,在本节中

    if (!this.props.userInfo && !this.props.history.location.pathname === '/') {
      this.props.history.replace("/");
      this.setState(this.state); // to rerender
    }
    

    您告诉组件在没有用户且路由不匹配“/”时重定向到“/”。因此,链接将路由更改为“/signin”,但随后又立即更改回“/”。

    【讨论】:

    • props 中没有 location 键。感谢提到历史操作中的逻辑错误。奇怪的是,浏览器导航栏中的路径变成了/signin。
    【解决方案2】:

    终于找到问题的原因了

    Home 和 App 组件连接到 redux 商店。 React-router 与 store 混淆,并使用 withRouter 函数处理。

    当我改变时

    const connectedPage = connect(mapStateToProps, { userRegister })(Home);

    const connectedPage = withRouter(connect(mapStateToProps, { userRegister })(Home));

    const connectedPage = connect(mapStateToProps, { })(App);

    const connectedPage = withRouter(connect(mapStateToProps, { })(App));

    它开始完美运行

    详情请查看:https://reacttraining.com/react-router/web/guides/redux-integration

    【讨论】: