Skip to content

Commit da2c45c

Browse files
committed
feat: improve <Link> and <Go>
1 parent 07baf31 commit da2c45c

File tree

3 files changed

+41
-22
lines changed

3 files changed

+41
-22
lines changed

src/Link/index.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Component, cloneElement} from 'react';
22
import {h, noop} from '../util';
3-
import {go} from '../route';
3+
import {go, TGo} from '../route/go';
44
import renderProp from '../util/renderProp';
55

66
const isModifiedEvent = (event) =>
@@ -12,13 +12,19 @@ export interface ILinkProps extends React.AllHTMLAttributes<any> {
1212
state?: any | ((props: ILinkProps) => any);
1313
to?: string;
1414
a?: boolean;
15+
onGo?: TGo;
16+
isActive?: boolean;
1517
}
1618

1719
export interface ILinkState {
1820

1921
}
2022

2123
export class Link extends Component<ILinkProps, any> {
24+
static defaultProps = {
25+
onGo: go
26+
};
27+
2228
el: HTMLElement = null;
2329
target: string = '';
2430

@@ -30,25 +36,26 @@ export class Link extends Component<ILinkProps, any> {
3036
onClick = (originalClick?) => (event) => {
3137
(originalClick || noop)(event);
3238

33-
const {replace, to, state} = this.props;
39+
const {onGo, replace, to, state} = this.props;
3440

3541
if (!event.defaultPrevented && // onClick prevented default
3642
event.button === 0 && // ignore everything but left clicks
37-
!this.target && // let browser handle "target=_blank" etc.
43+
!this.target && // let browser handle "target=*"
3844
!isModifiedEvent(event) // ignore clicks with modifier keys
3945
) {
4046
event.preventDefault();
4147

42-
go(to, {
48+
onGo(to, {
4349
replace,
4450
state: typeof state === 'function' ? state(this.props) : state
4551
});
4652
}
4753
};
4854

4955
render () {
50-
let {bond, replace, state, to, a, ...rest} = this.props;
56+
let {bond, replace, state, to, a, isActive, ...rest} = this.props;
5157
const renderPropState: any = {
58+
isActive,
5259
go,
5360
to
5461
};

src/route/__story__/StoryRouteTruncateRoute.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,16 @@ const StoryRouteTruncateRoute = () =>
66
<div>
77
<Router route='/api/users/123.json'>
88
<Route match='/api'>
9-
/api
10-
<div>
119
/api
1210
<Route match='/users'>
13-
<div>
14-
/api/users
11+
/api/users
1512
<Route match={/.*/}>{(result) =>
1613
<div>
1714
/api/users/.*
1815
<pre style={{fontFamily: 'monospace'}}>{JSON.stringify(result, null, 4)}</pre>
1916
</div>
2017
}</Route>
21-
</div>
2218
</Route>
23-
</div>
2419
</Route>
2520
</Router>
2621

@@ -29,20 +24,16 @@ const StoryRouteTruncateRoute = () =>
2924
<pre style={{fontFamily: 'monospace'}}>{`
3025
<Router route='/api/users/123.json'>
3126
<Route match='/api'>
32-
<div>
3327
/api
3428
<Route match='/users'>
35-
<div>
36-
/api/users
29+
/api/users
3730
<Route match={/.*/}>{(result) =>
3831
<div>
3932
/api/users/.*
4033
<pre style={{fontFamily: 'monospace'}}>{JSON.stringify(result, null, 4)}</pre>
4134
</div>
4235
}</Route>
43-
</div>
4436
</Route>
45-
</div>
4637
</Route>
4738
</Router>
4839
`}</pre>

src/route/index.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@ import {Provider, Consumer} from '../context';
44
import {h, ns} from '../util';
55
import renderProp from '../util/renderProp';
66
import {Link, ILinkProps} from '../Link';
7+
import {go, TGo} from './go';
8+
9+
export {
10+
go
11+
};
712

813
export interface IRouteProviderProps {
914
children?: any;
1015
ns?: string;
1116
fullRoute?: string;
1217
route?: string;
1318
parent?: TRouteMatchResult;
19+
onGo?: TGo;
1420
}
1521

1622
export class Router extends Component<IRouteProviderProps, any> {
23+
static defaultProps = {
24+
onGo: go
25+
};
26+
1727
matches: number = 0;
1828

1929
inc = () => {
@@ -27,6 +37,7 @@ export class Router extends Component<IRouteProviderProps, any> {
2737
const element = h(Provider, {
2838
name: ns(`route/${this.props.ns}`),
2939
value: {
40+
go: this.props.onGo,
3041
fullRoute: this.props.fullRoute || route,
3142
route,
3243
inc: this.inc,
@@ -107,7 +118,8 @@ export class Route extends Component<IRouteMatch, any> {
107118
};
108119

109120
render () {
110-
return h(Consumer, {name: ns(`route/${this.props.ns}`)}, ({route, inc, count, parent}) => {
121+
return h(Consumer, {name: ns(`route/${this.props.ns}`)}, (context) => {
122+
const {fullRoute, route, go, inc, count, parent} = context;
111123
const {children, exact, match, preserve, min, max} = this.props;
112124
const matchCount = count();
113125

@@ -132,9 +144,11 @@ export class Route extends Component<IRouteMatch, any> {
132144
parent: matchResult
133145
},
134146
renderProp(this.props, {
147+
go,
135148
match: route.substr(0, length),
136149
matches,
137150
route: newRoute,
151+
fullRoute,
138152
parent
139153
})
140154
);
@@ -151,20 +165,27 @@ export const Route404 = (props) => h(Route, {
151165
...props
152166
});
153167

154-
export * from './go';
155-
156168
export interface IGoProps extends ILinkProps {
169+
exact?: boolean;
170+
match?: TRouteMatcher | RegExp | string;
157171
ns?: string;
158172
}
159173

160174
export interface IGoState {
161-
162175
}
163176

164177
export class Go extends Component<IGoProps, IGoState> {
165178
render () {
166-
return h(Consumer, {name: ns(`route/${this.props.ns}`)}, ({fullRoute, route, inc, count, parent}) => {
167-
return h(Link, this.props)
179+
return h(Consumer, {name: ns(`route/${this.props.ns}`)}, ({fullRoute, route, go, inc, count, parent}) => {
180+
const {exact, match} = this.props;
181+
const matcher = createMatcher(match, exact);
182+
const isActive = !!matcher(fullRoute);
183+
184+
return h(Link, {
185+
...(this.props as ILinkProps),
186+
isActive,
187+
onGo: go
188+
})
168189
});
169190
}
170191
}

0 commit comments

Comments
 (0)