Компонент рендеринга слишком рано - PullRequest
3 голосов
/ 27 апреля 2019

Я пытаюсь создать PrivateRoute (HOC), чтобы проверить, был ли пользователь аутентифицирован (проверьте, существует ли «auth» в хранилище с избыточностью) перед отправкой его на фактический маршрут.Проблема в том, что личный кабинет завершает работу до того, как мой auth появляется в хранилище резервов.

console.log запускается дважды, первый раз, когда auth не появляется в хранилище, но это происходит во второй раз, но к тому времени, он уже перенаправил пользователя на экран входа в систему .... Как я могу дать достаточно времени для завершения выборки?Я знаю, как выполнить это условие, когда я просто хочу отобразить что-то условно (например, кнопки входа / выхода), но этот же подход не работает при попытке условно маршрутизировать кого-либо.

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Route } from 'react-router-dom'

class PrivateRoute extends Component {
  render() {
    const { component: Component, ...rest } = this.props
    console.log(this.props)

    return (
      <Route {...rest} render={(props) => (props.auth ? <Component {...props} /> : props.history.push('/login'))} />
    )
  }
}

function mapStateToProps({ auth }) {
  return { auth }
}

export default connect(mapStateToProps)(PrivateRoute)

Ответы [ 2 ]

1 голос
/ 28 апреля 2019

Когда создатель ваших действий возвращает токен, вам необходимо сохранить его в localStorage. и тогда вы можете создать, как показано ниже,

const store = createStore(
    reducers,
    { auth: { authenticated : localStorage.getItem('token') }},
    applyMiddleware(reduxThunk)
)

если пользователь уже вошел в систему, токен будет там. и начальное состояние установит токен в хранилище, поэтому вам не нужно вызывать создателя действий.

Теперь вам нужно обезопасить свои компоненты, проверив, вошел ли пользователь в систему или нет. Вот HOC для этого,

import React, { Component } from 'react';
import { connect } from 'react-redux';

export default ChildComponent => {
  class ComposedComponent extends Component {

    componentDidMount() {
      this.shouldNavigateAway();
    }

    componentDidUpdate() {
      this.shouldNavigateAway();
    }
    shouldNavigateAway() {
      if (!this.props.auth) {
        this.props.history.push('/');
      }
    }
    render() {
      return <ChildComponent {...this.props} />;
    }
  }
  function mapStateToProps(state) {
    return { auth: state.auth.authenticated };
  }
  return connect(mapStateToProps)(ComposedComponent);
};
1 голос
/ 27 апреля 2019

Я не использовал redux здесь, но я думаю, вы поняли бы главное.Надеюсь, что это поможет, и не стесняйтесь задавать любые вопросы!

import React, { Component } from "react";
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";

import Dashboard from "path/to/pages/Dashboard";

class App extends Component {
  state = {
    isLoggedIn: null,
  };

  componentDidMount () {
    // to survive F5
    // when page is refreshed all your in-memory stuff
    // is gone
    this.setState({ isLoggedIn: !!localStorage.getItem("sessionID") });
  }

  render () {
    return (
      <BrowserRouter>
        <Switch>
          <PrivateRoute
            path="/dashboard"
            component={Dashboard}
            isLoggedIn={this.state.isLoggedIn}
          />
          <Route path="/login" component={Login} />

          {/* if no url was matched -> goto login page */}
          <Redirect to="/login" />
        </Switch>
      </BrowserRouter>
    );
  }
}

class PrivateRoute extends Component {
  render () {
    const { component: Component, isLoggedIn, ...rest } = this.props;

    return (
      <Route
        {...rest}
        render={props =>
          isLoggedIn ? <Component {...props} /> : <Redirect to="/login" />
        }
      />
    );
  }
}

class Login extends Component {
  state = {
    login: "",
    password: "",
    sessionID: null,
  };

  componentDidMount () {
    localStorage.removeItem("sessionID");
  }

  handleFormSubmit = () => {
    fetch({
      url: "/my-app/auth",
      method: "post",
      body: JSON.strigify(this.state),
    })
      .then(response => response.json())
      .then(data => {
        localStorage.setItem("sessionID", data.ID);

        this.setState({ sessionID: data.ID });
      })
      .catch(e => {
        // error handling stuff
      });
  };

  render () {
    const { sessionID } = this.state;

    if (sessionID) {
      return <Redirect to="/" />;
    }

    return <div>{/* login form with it's logic */}</div>;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...