forked from remix-run/react-router
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLink.js
More file actions
126 lines (97 loc) · 2.86 KB
/
Link.js
File metadata and controls
126 lines (97 loc) · 2.86 KB
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import React, { Component } from 'react'
const { bool, object, string, func } = React.PropTypes
function isLeftClickEvent(event) {
return event.button === 0
}
function isModifiedEvent(event) {
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
}
function isEmptyObject(object) {
for (let p in object)
if (object.hasOwnProperty(p))
return false
return true
}
/**
* A <Link> is used to create an <a> element that links to a route.
* When that route is active, the link gets the value of its
* `activeClassName` prop
*
* For example, assuming you have the following route:
*
* <Route path="/posts/:postID" component={Post} />
*
* You could use the following component to link to that route:
*
* <Link to={`/posts/${post.id}`} />
*
* Links may pass along location state and/or query string parameters
* in the state/query props, respectively.
*
* <Link ... query={{ show: true }} state={{ the: 'state' }} />
*/
class Link extends Component {
handleClick(event) {
let allowTransition = true
if (this.props.onClick)
this.props.onClick(event)
if (isModifiedEvent(event) || !isLeftClickEvent(event))
return
if (event.defaultPrevented === true)
allowTransition = false
// If target prop is set (e.g. to "_blank") let browser handle link.
/* istanbul ignore if: untestable with Karma */
if (this.props.target) {
if (!allowTransition)
event.preventDefault()
return
}
event.preventDefault()
if (allowTransition) {
let { state, to, query, hash } = this.props
if (hash)
to += hash
this.context.history.pushState(state, to, query)
}
}
render() {
const { to, query, hash, state, activeClassName, activeStyle, onlyActiveOnIndex, ...props } = this.props
// Manually override onClick.
props.onClick = (e) => this.handleClick(e)
// Ignore if rendered outside the context of history, simplifies unit testing.
const { history } = this.context
if (history) {
props.href = history.createHref(to, query)
if (hash)
props.href += hash
if (activeClassName || (activeStyle != null && !isEmptyObject(activeStyle))) {
if (history.isActive(to, query, onlyActiveOnIndex)) {
if (activeClassName)
props.className += props.className === '' ? activeClassName : ` ${activeClassName}`
if (activeStyle)
props.style = { ...props.style, ...activeStyle }
}
}
}
return <a {...props} />
}
}
Link.contextTypes = {
history: object
}
Link.propTypes = {
to: string.isRequired,
query: object,
hash: string,
state: object,
activeStyle: object,
activeClassName: string,
onlyActiveOnIndex: bool.isRequired,
onClick: func
}
Link.defaultProps = {
onlyActiveOnIndex: false,
className: '',
style: {}
}
export default Link