1
- // This is largely taken from react-router/lib/Link.
2
-
3
- import React from 'react' ;
4
-
5
- function isLeftClickEvent ( event ) {
6
- return event . button === 0 ;
7
- }
8
-
9
- function isModifiedEvent ( event ) {
10
- return ! ! (
11
- event . metaKey ||
12
- event . altKey ||
13
- event . ctrlKey ||
14
- event . shiftKey
15
- ) ;
16
- }
17
-
18
- function createLocationDescriptor ( to , query , hash , state ) {
19
- if ( query || hash || state ) {
20
- return { pathname : to , query, hash, state } ;
21
- }
22
-
23
- return to ;
24
- }
25
-
26
- const propTypes = {
27
- onlyActiveOnIndex : React . PropTypes . bool . isRequired ,
28
- to : React . PropTypes . oneOfType ( [
29
- React . PropTypes . string ,
30
- React . PropTypes . object ,
31
- ] ) . isRequired ,
32
- query : React . PropTypes . string ,
33
- hash : React . PropTypes . string ,
34
- state : React . PropTypes . object ,
35
- action : React . PropTypes . oneOf ( [
36
- 'push' ,
37
- 'replace' ,
38
- ] ) . isRequired ,
39
- onClick : React . PropTypes . func ,
40
- active : React . PropTypes . bool ,
41
- target : React . PropTypes . string ,
42
- children : React . PropTypes . node . isRequired ,
43
- } ;
1
+ import React , { Component , PropTypes } from 'react' ;
2
+ import { Route } from 'react-router-dom' ;
3
+
4
+ const isModifiedEvent = ( event ) =>
5
+ ! ! ( event . metaKey || event . altKey || event . ctrlKey || event . shiftKey ) ;
6
+
7
+ export default class LinkContainer extends Component {
8
+ static contextTypes = {
9
+ router : PropTypes . shape ( {
10
+ history : PropTypes . shape ( {
11
+ push : PropTypes . func . isRequired ,
12
+ replace : PropTypes . func . isRequired ,
13
+ createHref : PropTypes . func . isRequired ,
14
+ } ) . isRequired ,
15
+ } ) . isRequired ,
16
+ } ;
44
17
45
- const contextTypes = {
46
- router : React . PropTypes . object ,
47
- } ;
18
+ static propTypes = {
19
+ children : PropTypes . element . isRequired ,
20
+ onClick : PropTypes . func ,
21
+ replace : PropTypes . bool ,
22
+ to : PropTypes . oneOfType ( [
23
+ PropTypes . string ,
24
+ PropTypes . object ,
25
+ ] ) . isRequired ,
26
+ exact : PropTypes . bool ,
27
+ strict : PropTypes . bool ,
28
+ className : PropTypes . string ,
29
+ activeClassName : PropTypes . string ,
30
+ style : PropTypes . object ,
31
+ activeStyle : PropTypes . object ,
32
+ isActive : PropTypes . func ,
33
+ } ;
48
34
49
- const defaultProps = {
50
- onlyActiveOnIndex : false ,
51
- action : 'push' ,
52
- } ;
35
+ static defaultProps = {
36
+ replace : false ,
37
+ exact : false ,
38
+ strict : false ,
39
+ activeClassName : 'active' ,
40
+ } ;
53
41
54
- class LinkContainer extends React . Component {
55
- onClick = ( event ) => {
56
- const {
57
- to, query, hash, state, children, onClick, target, action,
58
- } = this . props ;
42
+ handleClick = ( event ) => {
43
+ const { children, onClick } = this . props ;
59
44
60
45
if ( children . props . onClick ) {
61
46
children . props . onClick ( event ) ;
@@ -66,42 +51,62 @@ class LinkContainer extends React.Component {
66
51
}
67
52
68
53
if (
69
- target ||
70
- event . defaultPrevented ||
71
- isModifiedEvent ( event ) ||
72
- ! isLeftClickEvent ( event )
54
+ ! event . defaultPrevented && // onClick prevented default
55
+ event . button === 0 && // ignore right clicks
56
+ ! isModifiedEvent ( event ) // ignore clicks with modifier keys
73
57
) {
74
- return ;
75
- }
58
+ event . preventDefault ( ) ;
76
59
77
- event . preventDefault ( ) ;
60
+ const { history } = this . context . router ;
61
+ const { replace, to } = this . props ;
78
62
79
- this . context . router [ action ] (
80
- createLocationDescriptor ( to , query , hash , state )
81
- ) ;
82
- } ;
63
+ if ( replace ) {
64
+ history . replace ( to ) ;
65
+ } else {
66
+ history . push ( to ) ;
67
+ }
68
+ }
69
+ }
83
70
84
71
render ( ) {
85
- const { router } = this . context ;
86
- const { onlyActiveOnIndex, to, children, ...props } = this . props ;
87
-
88
- props . onClick = this . onClick ;
89
-
90
- // Ignore if rendered outside Router context; simplifies unit testing.
91
- if ( router ) {
92
- props . href = router . createHref ( to ) ;
72
+ const {
73
+ children,
74
+ replace, // eslint-disable-line no-unused-vars
75
+ to,
76
+ exact,
77
+ strict,
78
+ activeClassName,
79
+ className,
80
+ activeStyle,
81
+ style,
82
+ isActive : getIsActive ,
83
+ ...props ,
84
+ } = this . props ;
93
85
94
- if ( props . active == null ) {
95
- props . active = router . isActive ( to , onlyActiveOnIndex ) ;
96
- }
97
- }
86
+ const href = this . context . router . history . createHref (
87
+ typeof to === 'string' ? { pathname : to } : to
88
+ ) ;
98
89
99
- return React . cloneElement ( React . Children . only ( children ) , props ) ;
90
+ return (
91
+ < Route
92
+ path = { typeof to === 'object' ? to . pathname : to }
93
+ exact = { exact }
94
+ strict = { strict }
95
+ children = { ( { location, match } ) => {
96
+ const isActive = ! ! ( getIsActive ? getIsActive ( match , location ) : match ) ;
97
+
98
+ return React . cloneElement (
99
+ React . Children . only ( children ) ,
100
+ {
101
+ ...props ,
102
+ className : isActive ? [ className , activeClassName ] . join ( ' ' ) : className ,
103
+ style : isActive ? { ...style , ...activeStyle } : style ,
104
+ href,
105
+ onClick : this . handleClick ,
106
+ }
107
+ ) ;
108
+ } }
109
+ />
110
+ ) ;
100
111
}
101
112
}
102
-
103
- LinkContainer . propTypes = propTypes ;
104
- LinkContainer . contextTypes = contextTypes ;
105
- LinkContainer . defaultProps = defaultProps ;
106
-
107
- export default LinkContainer ;
0 commit comments