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+ } ;
4417
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+ } ;
4834
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+ } ;
5341
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 ;
5944
6045 if ( children . props . onClick ) {
6146 children . props . onClick ( event ) ;
@@ -66,42 +51,62 @@ class LinkContainer extends React.Component {
6651 }
6752
6853 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
7357 ) {
74- return ;
75- }
58+ event . preventDefault ( ) ;
7659
77- event . preventDefault ( ) ;
60+ const { history } = this . context . router ;
61+ const { replace, to } = this . props ;
7862
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+ }
8370
8471 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 ;
9385
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+ ) ;
9889
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+ ) ;
100111 }
101112}
102- 103- LinkContainer . propTypes = propTypes ;
104- LinkContainer . contextTypes = contextTypes ;
105- LinkContainer . defaultProps = defaultProps ;
106- 107- export default LinkContainer ;
0 commit comments