В 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
когда пользователь выходит из системы.