基本使用方式
设计路由结构(嵌套和路由参数):
- Home
- About
- Topic
- Rendering
- Component
- Prop v state
1 | import React from 'react' |
重定向
以用户登陆为例,主要通过自定义路由,重定向来完成登陆功能。
主界面, public为公共界面,不登陆也能浏览,Proteted界面只有登陆了之后才能进入,否则会显示登陆提示。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const AuthExample = () => (
<Router>
<div>
<AuthButton />
<ul>
<li>
<Link to="/public">Public Page</Link>
</li>
<li>
<Link to="/protected">Protected Page</Link>
</li>
</ul>
<Route path="/public" component={Public} />
<Route path="/login" component={Login} />
<PrivateRoute path="/protected" component={Protected} />
</div>
</Router>
)
登陆标志,以及登陆和退出的方法,这里用定时器来模拟异步。1
2
3
4
5
6
7
8
9
10
11const fakeAuth = {
isAuthenticated: false,
authenticate(cb) {
this.isAuthenticated = true
setTimeout(cb, 100)
},
signout(cb) {
this.isAuthenticated = false
setTimeout(cb, 100)
},
}
退出按钮,由于登陆成功后,需要重新回到主页,因此可以使用withRouter高阶组件,通过该组件,可以在任何地方访问打history对象。我们可以将路由想象成一个栈的存储结构,通过push方法,可以替换当前栈中的条目,这个方法可以解决用户退出后,使用浏览器后退按钮时,依然可以进入被保护的页面的问题。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const AuthButton = withRouter(
({ history }) =>
fakeAuth.isAuthenticated ? (
<p>
Welcome!{' '}
<button
onClick={() => {
fakeAuth.signout(() => history.push('/'))
}}
>
Sign out
</button>
</p>
) : (
<p>You are not logged in.</p>
),
)
自定义路由,本质是对Route组件的包装。由于protected具有权限性,只有登陆的用户才能查看,而没有登陆的用户会重定向到登陆界面,所以需要通过自定义路由来对该页面进行权限判定。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: '/login',
state: { from: props.location },
}}
/>
)
}
/>
)
Login组件有一个需要注意的地方,一般地,为了提高用户的体验度,登陆成功之后,需要重定向回到登陆之前的界面,例如我们是从protected界面进入login界面的,则重定向至protected界面,而不是跳转至其它界面。通过location.state.from能看到是从哪个界面进入界面的,也就是字面意思的,来自哪个界面。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
31const Public = () => <h3>Public</h3>
const Protected = () => <h3>Protected</h3>
class Login extends React.Component {
state = {
redirectToReferrer: false,
}
login = () => {
fakeAuth.authenticate(() => {
this.setState({ redirectToReferrer: true })
})
}
render() {
const { from } = this.props.location.state || { from: { pathname: '/' } }
const { redirectToReferrer } = this.state
if (redirectToReferrer) {
return <Redirect to={from} />
}
return (
<div>
<p>You must log in to view the page at {from.pathname}</p>
<button onClick={this.login}>Log in</button>
</div>
)
}
}
Switch(构建404页面的路由)
需要解决的问题: 一个组件下有多个route,而我们只要去匹配到其中一个route,如果匹配成功,则只显示该route的内容,而不需要继续往下判断。在这个例子中我们会构造许多链接,如果该链接的路由不存在,那么会自动进入404页面。
1 | const NoMatchExample = () => ( |