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' ;
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+ push : PropTypes . func . isRequired ,
11+ replace : PropTypes . func . isRequired ,
12+ createHref : PropTypes . func . isRequired ,
13+ } ) . isRequired ,
14+ } ;
4415
45- const contextTypes = {
46- router : React . PropTypes . object ,
47- } ;
16+ static propTypes = {
17+ children : PropTypes . element . isRequired ,
18+ onClick : PropTypes . func ,
19+ target : PropTypes . string ,
20+ replace : PropTypes . bool ,
21+ to : PropTypes . oneOfType ( [
22+ PropTypes . string ,
23+ PropTypes . object ,
24+ ] ) . isRequired ,
25+ exact : PropTypes . bool ,
26+ strict : PropTypes . bool ,
27+ className : PropTypes . string ,
28+ activeClassName : PropTypes . string ,
29+ style : PropTypes . object ,
30+ activeStyle : PropTypes . object ,
31+ isActive : PropTypes . func ,
32+ } ;
4833
49- const defaultProps = {
50- onlyActiveOnIndex : false ,
51- action : 'push ' ,
52- } ;
34+ static defaultProps = {
35+ replace : false ,
36+ activeClassName : 'active ' ,
37+ } ;
5338
54- class LinkContainer extends React . Component {
55- onClick = ( event ) => {
56- const {
57- to, query, hash, state, children, onClick, target, action,
58- } = this . props ;
39+ handleClick = ( event ) => {
40+ const { children, onClick } = this . props ;
5941
6042 if ( children . props . onClick ) {
6143 children . props . onClick ( event ) ;
@@ -66,42 +48,63 @@ class LinkContainer extends React.Component {
6648 }
6749
6850 if (
69- target ||
70- event . defaultPrevented ||
71- isModifiedEvent ( event ) ||
72- ! isLeftClickEvent ( event )
51+ ! event . defaultPrevented && // onClick prevented default
52+ event . button === 0 && // ignore right clicks
53+ ! this . props . target && // let browser handle "target=_blank" etc.
54+ ! isModifiedEvent ( event ) // ignore clicks with modifier keys
7355 ) {
74- return ;
75- }
56+ event . preventDefault ( ) ;
7657
77- event . preventDefault ( ) ;
58+ const { router } = this . context ;
59+ const { replace, to } = this . props ;
7860
79- this . context . router [ action ] (
80- createLocationDescriptor ( to , query , hash , state )
81- ) ;
82- } ;
61+ if ( replace ) {
62+ router . replace ( to ) ;
63+ } else {
64+ router . push ( to ) ;
65+ }
66+ }
67+ }
8368
8469 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 ) ;
70+ const {
71+ children,
72+ replace, // eslint-disable-line no-unused-vars
73+ to,
74+ exact,
75+ strict,
76+ activeClassName,
77+ className,
78+ activeStyle,
79+ style,
80+ isActive : getIsActive ,
81+ ...props ,
82+ } = this . props ;
9383
94- if ( props . active == null ) {
95- props . active = router . isActive ( to , onlyActiveOnIndex ) ;
96- }
97- }
84+ const href = this . context . router . createHref (
85+ typeof to === 'string' ? { pathname : to } : to
86+ ) ;
9887
99- return React . cloneElement ( React . Children . only ( children ) , props ) ;
88+ return (
89+ < Route
90+ path = { typeof to === 'object' ? to . pathname : to }
91+ exact = { exact }
92+ strict = { strict }
93+ children = { ( { location, match } ) => {
94+ const isActive = ! ! ( getIsActive ? getIsActive ( match , location ) : match ) ;
95+
96+ return React . cloneElement (
97+ React . Children . only ( children ) ,
98+ {
99+ ...props ,
100+ className : ( className || '' ) + ( isActive ? activeClassName : '' ) ,
101+ style : isActive ? { ...style , ...activeStyle } : style ,
102+ href,
103+ onClick : this . handleClick ,
104+ }
105+ ) ;
106+ } }
107+ />
108+ ) ;
100109 }
101110}
102-
103- LinkContainer . propTypes = propTypes ;
104- LinkContainer . contextTypes = contextTypes ;
105- LinkContainer . defaultProps = defaultProps ;
106-
107- export default LinkContainer ;
0 commit comments