我在ReactJS中创建了一系列路由
const routes = [
{ id: 0, path: '/', view: Home, parent: 0 },
{ id: 1, path: '/a', view: Home2, parent: 0 },
{ id: 2, path: '/b', view: Home3, parent: 1 }
]
创建了HOC withAuth,当用户未记录时,它应返回到父路由。当我要去路线(因为没有记录) - 它的确定和withAuth将我带回到父路线,但是当我在路线上并且注销页面没有刷新时我会留在路由记录用户。
import React, { Component } from "react";
import AuthHelper from "./AuthHelper";
export default function withAuth(AuthComponent) {
const Auth = new AuthHelper();
class AuthWrapped extends Component {
constructor(props) {
super(props);
this.state = {
confirm: null,
loaded: false
};
}
checkLogged = () => {
if (!Auth.loggedIn()) {
const parent = this.props.parent;
const obj = this.props.routes
.filter(v => v.id === parent);
this.props.history.replace(obj[0].path);
} else {
try {
const confirm = Auth.getConfirm();
this.setState({
confirm: confirm,
loaded: true
});
} catch (err) {
Auth.logout();
this.props.history.replace("/");
}
}
}
componentDidMount() {
this.checkLogged();
}
render() {
if (this.state.loaded) {
if (this.state.confirm) {
return (
<AuthComponent
history={this.props.history}
confirm={this.state.confirm}
/>
);
} else {
return null;
}
} else {
return null;
}
}
};
return AuthWrapped;
}
我相信你是以错误的方式使用身份验证系统 在React中,一切都应该以分层方式存在。
在你的情况下,你有一个可以改变的Auth状态,当loggedIn状态改变时,一切都应该重新渲染。正确的方法是使用Context API来处理登录状态,这样当状态改变时,整个屏幕将重新渲染
这是您的问题的解决方案:
AuthContext.js
const AuthContext = React.createContext();
export class AuthProvider extends React.Component {
state = {
isLoggedIn: false,
};
login = (username, password) => {
someLoginRequestToServer(username, password).then(response => {
this.setState({
isLoggedIn: response.isLoggedIn,
});
});
};
logout = () => {
someLogoutRequestToServer().then(() => {
this.setState({ isLoggedIn: false });
});
};
render() {
return (
<AuthContext.Provider
value={{
loggedIn: this.state.isLoggedIn,
login: this.login,
logout: this.logout,
}}>
{this.props.children}
</AuthContext.Provider>
);
}
}
export const AuthConsumer = AuthContext.Consumer;
SomeCustomAuthComponent
class CustomAuthComponent extends React.Component {
render() {
return (
<AuthConsumer>
{({ loggedIn, login, logout }) => (
<div>
<p>You Are {loggedIn ? 'Logged in' : 'Logged out'}</p>
<button onClick={loggedIn ? () => logout() : () => login('abcd', '12345')} />
</div>
)}
</AuthConsumer>
);
}
}
或者你可以使用redux进行状态管理和react-redux,因为它使用了反应中的Context API。
希望这对你有所帮助! :)
这个问题就在这里
componentDidMount() {
this.checkLogged();
}
您正在检查用户是否仅在安装组件时进行了记录(在实例化之后)。你应该在每次页面更新时检查它,你必须找到一种方法来处理这种机制,例如使用componentDidUpdate
钩子。
export default function withAuth(AuthComponent) {
const Auth = new AuthHelper();
class AuthWrapped extends Component {
constructor(props) {
super(props);
this.state = {
confirm: null,
loaded: false
};
}
checkIsNotLogged = () => {
const parent = this.props.parent;
const obj = this.props.routes
.filter(v => v.id === parent);
this.props.history.replace(obj[0].path);
}
checkLogged = () => {
if (!Auth.loggedIn()) {
this.checkIsNotLogged();
} else {
try {
const confirm = Auth.getConfirm();
this.setState({
confirm: confirm,
loaded: true
});
} catch (err) {
Auth.logout();
this.props.history.replace("/");
}
}
}
componentDidMount() {
this.checkLogged();
}
componentDidUpdate() {
// do not call here the checkLogged method otherwise you could trigger an infinite loop
this.checkIsNotLogged();
}
render() {
if (this.state.loaded) {
if (this.state.confirm) {
return (
<AuthComponent
history={this.props.history}
confirm={this.state.confirm}
/>
);
} else {
return null;
}
} else {
return null;
}
}
};
return AuthWrapped;
}