Skip to content

Commit 4dfd6ff

Browse files
committed
added activeClass to Link
1 parent 34c9061 commit 4dfd6ff

File tree

8 files changed

+210
-97
lines changed

8 files changed

+210
-97
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ cache:
1010
script:
1111
- yarn global add typings
1212
- typings install
13-
- yarn run transpile
13+
- yarn run build
1414

1515
deploy:
1616
provider: npm

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"clean": "rm -rf lib",
2020
"watch": "yarn run clean && tsc -p . --watch",
2121
"transpile": "yarn run clean && tsc -p .",
22+
"build": "yarn run clean && tsc --outDir ./ -p .",
2223
"tsc": "tsc"
2324
},
2425
"devDependencies": {

src/browser-router.tsx

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import * as React from 'react';
2+
import Router, { initParams, initResult } from './router';
3+
import { Context } from 'router-async';
4+
5+
export default class BrowserRouter extends Router {
6+
private history: any;
7+
private unlistenHistroy: any;
8+
constructor(props) {
9+
super(props);
10+
this.history = props.history;
11+
}
12+
static async init(opts: initParams): Promise<initResult> {
13+
const result = await super.init(opts);
14+
return {
15+
...result,
16+
Router: BrowserRouter
17+
};
18+
}
19+
static childContextTypes = {
20+
router: React.PropTypes.object
21+
};
22+
getChildContext() {
23+
return {
24+
router: this
25+
};
26+
}
27+
async navigate(path, ctx = new Context()) {
28+
try {
29+
const { redirect } = await this.router.match({ path, ctx });
30+
if (redirect) {
31+
this.history.push(redirect);
32+
} else {
33+
this.history.push(path);
34+
}
35+
} catch (error) {
36+
this.history.push(path);
37+
if (!this.props.errorHandler) {
38+
console.error('Match Error', path, error);
39+
throw error;
40+
}
41+
}
42+
}
43+
// TODO: maybe we need to make this history methods works through navigate?
44+
goBack() {
45+
this.history.goBack();
46+
}
47+
goForward() {
48+
this.history.goForward();
49+
}
50+
go(n) {
51+
this.history.go(n);
52+
}
53+
private _locationChanged = async ({ pathname }) => {
54+
try {
55+
const { path, location, route, status, params, redirect, result, ctx } = await this.router.run({ path: pathname });
56+
const props = {
57+
router: {
58+
path,
59+
location,
60+
route,
61+
status,
62+
params,
63+
redirect,
64+
ctx
65+
}
66+
};
67+
const renderCallback = Router.makeCallback(this.router, { path, route, status, params, redirect, result, ctx });
68+
this.changeComponent({ Component: result, componentProps: props, path, location, renderCallback });
69+
} catch (error) {
70+
if (this.props.errorHandler) {
71+
this.props.errorHandler(error, this);
72+
} else {
73+
console.error('Resolve Error', location, error);
74+
throw error;
75+
}
76+
}
77+
};
78+
componentDidMount() {
79+
this.unlistenHistroy = this.history.listen(this._locationChanged)
80+
}
81+
componentWillUnmount() {
82+
this.unlistenHistroy();
83+
}
84+
}

src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import Router from './router';
1+
import BrowserRouter from './browser-router';
2+
import ServerRouter from './server-router';
23
import Route from './route';
34
import Link from './link';
45
import RootRoute from './root-route';
@@ -8,7 +9,8 @@ import PlaceHolder from './placeholder';
89
import { RouterError, Context } from 'router-async';
910

1011
export {
11-
Router,
12+
BrowserRouter,
13+
ServerRouter,
1214
Route,
1315
Link,
1416
RootRoute,

src/link.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,30 @@ export default class Link extends React.Component<Props, State> {
1414
static contextTypes = {
1515
router: React.PropTypes.object
1616
};
17+
static isActive(to, path, activeOnlyWhenExact) {
18+
return activeOnlyWhenExact ? path === to : path.indexOf(to) === 0;
19+
};
1720
navigate = e => {
1821
this.context.router.navigate(this.props.to);
1922
e.preventDefault();
2023
};
2124
render() {
2225
const {
2326
to,
27+
className,
28+
activeClassName,
29+
activeOnlyWhenExact,
2430
...rest
2531
} = this.props;
32+
const isActive = Link.isActive(to, this.context.router.getState().location.pathname, activeOnlyWhenExact);
2633

27-
return <a href={to} onClick={this.navigate} {...rest}>{this.props.children}</a>;
34+
return (
35+
<a
36+
{...rest}
37+
href={to}
38+
onClick={this.navigate}
39+
className={isActive ? [className, activeClassName].join(' ').trim() : className}
40+
/>
41+
);
2842
}
2943
}

src/placeholder.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ export interface Props {
66
}
77
export interface State {
88
Component?: React.ComponentClass<Props>,
9-
props?: any;
9+
componentProps?: any;
10+
path?: any;
11+
location?: any;
1012
}
1113
export interface Context {
1214
router: Router
@@ -16,22 +18,24 @@ export default class PlaceHolder extends React.Component<Props, State> {
1618
static contextTypes = {
1719
router: React.PropTypes.object.isRequired
1820
};
19-
constructor(props) {
21+
constructor({ Component, componentProps }) {
2022
super();
2123
this.state = {
22-
Component: props.Component,
23-
props: props.props
24+
Component,
25+
componentProps
2426
};
2527
}
2628
componentDidMount() {
27-
this.context.router.subscribe((Component, props, renderCallback) => {
29+
this.context.router.subscribe(({ Component, componentProps, path, location, renderCallback }) => {
2830
this.setState({
31+
path,
32+
location,
2933
Component,
30-
props
34+
componentProps
3135
}, renderCallback);
3236
})
3337
}
3438
render() {
35-
return <this.state.Component router={this.state.props} />
39+
return <this.state.Component {...this.state.componentProps} />
3640
}
3741
}

0 commit comments

Comments
 (0)