В React попытка обновить и остаться на той же странице, но состояние не будет обновляться должным образом

В моем приложении используются response, response-router-dom и stitch, которые получают доступ к mongodb и обрабатывают аутентификацию через google. Я могу пройти аутентификацию и получить доступ к компоненту ProtectedPage, но когда я обновлюсь, isAuthed не будет иметь значения, и я перенаправлю его на / login. Почему состояние не обновляется, так что isAuthed = true, и как мне убедиться, что я попал в / защищен при обновлении?

import React, {Component} from 'react';
import {
  Switch,
  Route,
  Link,
  Redirect,
  withRouter,
} from "react-router-dom";
import {Stitch, GoogleRedirectCredential} from 'mongodb-stitch-browser-sdk'

import './App.css';

class App extends Component{

  constructor(props) {
    super(props)

    this.state = {
      isAuthed: ''
    }
  }

  componentDidMount(){
    
    this.client = new Stitch.initializeDefaultAppClient("myAppId");

    if(this.client.auth.hasRedirectResult()){
      this.client.auth.handleRedirectResult();
    }
    
    this.setState({isAuthed: this.client.auth.isLoggedIn});
  }


  login = () => {
    const credential = new GoogleRedirectCredential() 
    this.user = this.client.auth.loginWithRedirect(credential);
  }

  logout = () => {
    this.client.auth.logout();
    this.setState({isAuthed: false});
  }

  showUser = () => {
    console.log(this.client.auth.isLoggedIn);
    console.log(this.client);
  }


  render() {
  return (
    <div className="App">
    <ul>
      <li>
        <Link to="/">Public Page</Link>
      </li>
      <li>
        <Link to="/login">Login</Link>
      </li>
      <li>
      <Link to="/protected">Protected Page</Link>
    </li>
    </ul>

    <Switch>
      <Route exact path="/">
        <PublicPage isAuthed={this.state.isAuthed}/>
      </Route>
      <Route path="/login" >
        <LoginPage login={this.login} isAuthed={this.state.isAuthed}/>
      </Route>
      <PrivateRoute path="/protected" isAuthed={this.state.isAuthed} >
        <ProtectedPage logout={this.logout} />
      </PrivateRoute>
    </Switch>

    </div>
  );
  }
}

export default withRouter(App);

function PublicPage() {
 
  return (
    <div><h3>Public</h3>
    </div>
    
  );

}

function ProtectedPage({logout}) {
 
  return (
      <div>
      <h3>You Are Logged In</h3>
        <button onClick={logout}>Logout</button>
      </div>
    );
}

function LoginPage({login}) {

  return (


    <div>
      <p>You must log in to view the page</p>
      <button onClick={login}>Log in</button>
    </div>
    
  );
}

function PrivateRoute({ children, isAuthed, client, ...rest}) {
  console.log(isAuthed);

  return (
    <Route
      {...rest}
      render={({ location }) =>
      isAuthed ? (
          children
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: location }
            }}
          />
        )
      }
    />
  );
}

2 ответа

ComponentDidMount вызывается только после первого вызова метода рендеринга. Попробуйте поместить код в componentWillMount вместо componentDidMount.

Я бы предложил хранить информацию о пользователе в локальном хранилище браузера вместо хранения isAuthed в состоянии.

Состояние в React эфемерно. Всякий раз, когда вы перезагружаете страницу или выполняете перенаправление, которое вызывает запрос GET для новой страницы, состояние сбрасывается на то, что вы установили по умолчанию, что в случаеthis.state.isAuthed является "".

Чтобы решить проблему, вы можете сохранить isAuthed состояние в localStorage или как файл cookie всякий раз, когда пользователь входит в систему. Затем вы можете получить это значение и установить свое состояние при первой загрузке страницы, используя componentDidMount или useEffect.

Просто не забудьте очистить свой localStorage или значения cookie для isAuthed когда пользователь выходит из системы.

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