Невозможно сделать так, чтобы маршруты рендеринга React-Router 4 были правильными

У меня есть это простое приложение с 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 имеет значение null), тогда я хочу, чтобы путь был / и отображал компонент 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;

Также у меня есть Link на компоненте Home, который меняет путь в панели навигации браузера, но не влияет на визуализированный компонент 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;

Я чувствую, что мне не хватает чего-то очень простого в маршрутизации с помощью response-router.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
325
2

Ответы 2

Попробуйте использовать this.props.location вместо this.props.history.location. См. эта часть документов.

Что касается ссылки, то в этом разделе

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

Вы говорите компоненту перенаправить на '/' каждый раз, когда нет пользователя и маршрут не совпадает с '/'. Таким образом, ссылка меняет маршрут на '/ signin', но затем сразу же возвращается обратно на '/'.

В реквизите нет ключа местоположения. Спасибо за упоминание логической ошибки в манипулировании историей. Странно то, что в панели навигации браузера путь меняется на / signin.

zuba 05.09.2018 09:52

Наконец выяснилось, что вызвало неприятности

Компоненты Home и App подключены к redux store. React-router возится с магазином и обрабатывает это с помощью функции 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

Другие вопросы по теме