-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 🎸 Make new version of Route work
- Loading branch information
Showing
6 changed files
with
123 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import render from '../util/renderProp'; | ||
import Router from './Router'; | ||
import {Consumer} from '../context'; | ||
import {h, ns} from '../util'; | ||
import createMatcher, {TRouteMatcher, TRouteMatchResult} from './createMatcher'; | ||
import {IUniversalInterfaceProps} from '../typing'; | ||
|
||
export interface IRouteData { | ||
fullRoute: string; | ||
route: string; | ||
parent: IRouteData; | ||
match: TRouteMatchResult; | ||
} | ||
|
||
export interface IRouteProps extends IUniversalInterfaceProps<IRouteData> { | ||
ns?: string; | ||
exact?: boolean; | ||
match?: TRouteMatcher | RegExp | string; | ||
truncate?: boolean; | ||
} | ||
|
||
const Route: React.SFC<IRouteProps> = (props) => { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (typeof props.match !== 'string') { | ||
if (props.exact) { | ||
console.warn( | ||
'You are using <Route exact /> with non-string match prop, ' + | ||
'exact prop works only with string match prop.' | ||
); | ||
} | ||
} | ||
} | ||
|
||
return h(Consumer, {name: ns(`route/${props.ns}`)}, (context) => { | ||
const {exact, match, truncate} = props; | ||
const {fullRoute, route, parent} = context; | ||
const matches = createMatcher(match, exact)(route); | ||
|
||
if (!matches) { | ||
return null; | ||
} | ||
|
||
const data = { | ||
fullRoute, | ||
route, | ||
parent, | ||
matches, | ||
}; | ||
|
||
let element = render(props, data); | ||
|
||
if (truncate) { | ||
const routerProps = { | ||
fullRoute: route, | ||
route: route.substr(matches[0].length), | ||
parent: data, | ||
} as any; | ||
|
||
element = h(Router, routerProps, element); | ||
} | ||
|
||
return element; | ||
}); | ||
}; | ||
|
||
Route.defaultProps = { | ||
match: '', | ||
exact: false | ||
}; | ||
|
||
export default Route; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,34 @@ | ||
import {Component, Children} from 'react'; | ||
import {Children} from 'react'; | ||
import {Consumer} from '../context'; | ||
import {h, ns} from '../util'; | ||
import Route from './Route'; | ||
import createMatcher from './createMatcher'; | ||
|
||
const Switch = ({children}) => { | ||
const routes = Children.toArray(children); | ||
export interface ISwitchProps { | ||
ns?: string; | ||
} | ||
|
||
let route = null; | ||
const Switch: React.SFC<ISwitchProps> = (props) => { | ||
return h(Consumer, {name: ns(`route/${props.ns}`)}, (route) => { | ||
const routes = Children.toArray(props.children); | ||
|
||
for (let i = 0; i < routes.length; i++) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
// TODO: check that each element is a Route. | ||
} | ||
|
||
const {match, exact} = (routes[i] as any).props; | ||
const matchResult = createMatcher(match, exact)(route); | ||
for (let i = 0; i < routes.length; i++) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if ((typeof routes[i] !== 'object') || ((routes[i] as any).type !== Route)) { | ||
throw new TypeError('All <Switch> children must be <Route> elements.'); | ||
} | ||
} | ||
|
||
if (matchResult) { | ||
route = routes[i]; | ||
const {match, exact} = (routes[i] as any).props; | ||
const matchResult = createMatcher(match, exact)(route); | ||
|
||
break; | ||
if (matchResult) { | ||
return routes[i]; | ||
} | ||
} | ||
} | ||
|
||
return route; | ||
return null; | ||
}); | ||
}; | ||
|
||
export default Switch; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,12 @@ | ||
import {Component} from 'react'; | ||
import {render} from 'react-universal-interface'; | ||
import Router from './Router'; | ||
import {Consumer} from '../context'; | ||
import {h, ns} from '../util'; | ||
import Route from './Route'; | ||
import Switch from './Switch'; | ||
import {go, Go} from './go'; | ||
import createMatcher, {TRouteMatcher} from './createMatcher'; | ||
|
||
export { | ||
Router, | ||
Route, | ||
Switch, | ||
go, | ||
Go, | ||
}; | ||
|
||
export interface IRouteMatch { | ||
children?: any; | ||
render?: React.ReactElement<any> | ((params) => React.ReactElement<any>); | ||
comp?: React.ComponentClass<any> | React.StatelessComponent<any>; | ||
component?: React.ComponentClass<any> | React.StatelessComponent<any>; | ||
exact?: boolean; | ||
match?: TRouteMatcher | RegExp | string; | ||
min?: number; | ||
max?: number; | ||
ns?: string; | ||
preserve?: boolean; | ||
} | ||
|
||
export class Route extends Component<IRouteMatch, any> { | ||
static defaultProps = { | ||
match: /.+/, | ||
min: 0, | ||
max: Infinity | ||
}; | ||
|
||
render () { | ||
return h(Consumer, {name: ns(`route/${this.props.ns}`)}, (context) => { | ||
const {fullRoute, route, go, inc, count, parent} = context; | ||
const {exact, match, preserve, min, max} = this.props; | ||
const matchCount = count(); | ||
|
||
if ((matchCount >= min) && (matchCount <= max)) { | ||
const matchResult = createMatcher(match, exact)(route); | ||
|
||
if (matchResult) { | ||
// Increment number of matched routes. | ||
inc(); | ||
|
||
(matchResult as any).parent = parent; | ||
const {matches, length} = matchResult; | ||
let newRoute = route; | ||
|
||
if (!preserve && length) { | ||
newRoute = newRoute.substr(length); | ||
} | ||
|
||
return h(Router, { | ||
fullRoute: route, | ||
route: newRoute, | ||
parent: matchResult | ||
} as any, | ||
render(this.props, { | ||
go, | ||
match: route.substr(0, length), | ||
matches, | ||
route: newRoute, | ||
fullRoute, | ||
parent | ||
}) | ||
); | ||
} | ||
} | ||
|
||
return null; | ||
}); | ||
} | ||
} | ||
|
||
export const Route404 = (props) => h(Route, { | ||
max: 0, | ||
...props | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters