我正在使用react-router v4编写身份验证代码,我正在使用带有渲染道具的PrivateRoute,例如文档:Redirects (Auth)
我要做的是:每当用户导航到路线时,我都会发送一个动作来向后端发出请求以验证他是否已登录。
像这样:
// App.js
class App extends Component {
checkAuth = () => {
const { dispatch, } = this.props;
// callback to dispatch
}
render() {
const props = this.props;
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/" component={Login} />
<PrivateRoute
exact
path="/dashboard"
component={Dashboard}
checkIsLoggedIn={this.checkAuth}
/>
{/* ... other private routes here */}
</Switch>
</div>
</Router>
);
}
在PrivateRoute.js中,我正在侦听路由以检查它是否发生变化,但是当路由发生变化时,此函数被调用太多次,并且发送动作来发出请求是个问题。
// PrivateRoute.js
const PrivateRoute = ({ component: Component, auth, checkIsLoggedIn, ...rest }) => (
<Route
{...rest}
render={props => {
props.history.listen((location, action) => {
if (checkIsLoggedIn) {
// Here I check if the route changed, but it render too many times to make a request
checkIsLoggedIn(); // here is the callback props
}
});
if (auth.login.isLoggedIn) {
return <Component {...props} />;
} else {
return <Redirect to={{ pathname: "/login", state: { from: props.location } }} />
}
}
}
/>
);
我需要一个帮助,以便在路线发生变化时找出一个调用后端的好方法。
答案 0 :(得分:0)
创建Higher Order Component (HOC)是一种非常干净的方法。这样,您就不需要创建单独的PrivateRoute
组件,只需要一行更改就可以将任何组件从公共转换为受保护,反之亦然。
这样的事情应该有效:
import React from 'react';
import { Redirect } from "react-router-dom";
export function withAuth(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
isUserLoggedIn: false,
isLoading: true
};
}
componentDidMount() {
// Check for authentication when the component is mounted
this.checkAuthentication();
}
checkAuthentication() {
// Put some logic here to check authentication
// You can make a server call if you wish,
// but it will be faster if you read the logged-in state
// from cookies or something.
// Making a server call before every protected component,
// will be very expensive, and will be a poor user experience.
this.setState({
isUserLoggedIn: true, // Set to true or false depending upon the result of your auth check logic
isLoading: false
});
}
render() {
// Optionally, you can add logic here to show a common loading animation,
// or anything really, while the component checks for auth status.
// You can also return null, if you don't want any special handling here.
if (this.state.isLoading) return (<LoadingAnimation />);
// This part will load your component if user is logged in,
// else it will redirect to the login route
if (this.state.isUserLoggedIn) {
return <WrappedComponent authData={this.state} {...this.props} />;
} else {
return <Redirect to={{ pathname: "/login", state: { from: props.location } }} />;
}
}
}
}
一旦你有了这个组件,你需要做的就是在你想要保护的任何组件中使用HOC。例如,在您的情况下,Dashboard
文件中的导出行将是这样的:
/* Dashboard.js */
class Dashboard extends React.Component { ... }
export default withAuth(Dashboard);
在您的App
中,您可以使用简单的Route
组件:
<Route exact path='/dashboard' component={Dashboard} />
您的App
无需关心哪些路线受到保护,哪些路线不受保护。实际上,只有实际组件需要知道它们受到保护。
希望这会有所帮助。干杯! :)