React router private route not getting props from state (e.g. authentication state)
我正在尝试实现一个私有路由组件来重定向未通过身份验证的用户。问题是当我渲染像
在 App.js 请注意, PrivateRoute.js 问题与 如果您直接导航到
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class App extends Component {
state = {
currentUser: null,
isAuthenticated: false,
isLoading: false
}
loadCurrentUser = () => {
this.setState({
isLoading: true
});
// imported method
getCurrentUser()
.then(response => {
this.setState({
currentUser: response,
isAuthenticated: true,
isLoading: false
});
})
.catch(error => {
console.log(error)
this.setState({
isLoading: false
});
});
}
componentDidMount() {
this.loadCurrentUser();
}
handleLogin = () => {
this.loadCurrentUser();
this.props.history.push("/");
}
render () {
return (
<React.Fragment>
<Navigation
currentUser={this.state.currentUser}
isAuthenticated={this.state.isAuthenticated}
handleLogout={this.handleLogout} />
<Switch>
<PrivateRoute
authenticated={this.state.isAuthenticated}
exact
path='/postulante'
component={Panel}
currentUser={this.state.currentUser} />
<Route
exact
path='/'
render={
(props) => <Landing {...props} />
} />
<Route
path="/login"
exact
render={
(props) => <Login onLogin={this.handleLogin} {...props} />
} />
</Switch>
</React.Fragment>
);
}
}
export default withRouter(App);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const PrivateRoute = ({ component: Component, authenticated, ...rest }) => (
<Route
{...rest}
render={props =>
authenticated ? (
<Component {...rest} {...props} />
) : (
<Redirect
to={{
pathname: '/login',
state: { from: props.location }
}}
/>
)
}
/>
);
export default PrivateRoute
如果您从
最终,这就是为什么人们使用像 redux 这样的状态管理工具来让经过身份验证的状态在全球范围内共享,而不是通过父组件传递。
虽然有一个解决方法!
参考沙箱:https://codesandbox.io/s/intelligent-dan-uskcy
App 组件是否曾被初始化。我们称之为
我们直接进入它的组件路径,在 App 有机会完成它的
相反,我们将只显示一个空字符串,给父 App\\'s
现在让我们看一下这一行:
{...props} /> : !wasInitialized ? "" : <Redirect to="/login" />
}
在下一次重新渲染中,
错误的。如果用户是Authenticated,我们渲染预期的组件。如果用户未通过身份验证,我们进行下一个检查。现在 wasInitialized 的值为 true,因此 check 的计算结果为 false。因此,由于两个检查都没有通过,我们重定向到
应用程序.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | class App extends Component { state = { currentUser: null, isAuthenticated: false, isLoading: false, wasInitialized: false } loadCurrentUser = () => { this.setState({ isLoading: true }); // imported method getCurrentUser() .then(response => { this.setState({ currentUser: response, isAuthenticated: true, wasInitialized: true, isLoading: false }); }) .catch(error => { console.log(error) this.setState({ isLoading: false, wasInitialized: true }); }); } componentDidMount() { this.loadCurrentUser(); } handleLogin = () => { this.loadCurrentUser(); this.props.history.push("/"); } render () { return ( <React.Fragment> <Navigation currentUser={this.state.currentUser} isAuthenticated={this.state.isAuthenticated} handleLogout={this.handleLogout} /> <Switch> <PrivateRoute authenticated={this.state.isAuthenticated} path='/postulante' component={Panel} wasInitialized={this.state.wasInitialized} currentUser={this.state.currentUser} /> <Route exact path='/' render={ (props) => <Landing {...props} /> } /> <Route path="/login" exact render={ (props) => <Login onLogin={this.handleLogin} {...props} /> } /> </Switch> </React.Fragment> ); } } export default withRouter(App); |
私人的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import React from"react"; import { Route, Redirect } from"react-router-dom"; const PrivateRoute = ({ component: Component, auth, wasInitialized, ...rest }) => { return ( <Route {...rest} render={props => auth === true ? ( <Component {...props} /> ) : !wasInitialized ? ( "" ) : ( <Redirect to="/login" /> ) } /> ); }; export default PrivateRoute; |