Skip to content

Commit 8e4a60c

Browse files
committed
sneak peek preview release
1 parent d5605e1 commit 8e4a60c

File tree

14 files changed

+458
-6
lines changed

14 files changed

+458
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.idea
22
node_modules
3+
dev_modules
34
*.log
45
lib
56
typings

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# React Router Async
2+
[![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges)
3+
[![Latest Stable Version](https://img.shields.io/npm/v/react-router-async.svg?style=flat-square)](https://www.npmjs.com/package/react-router-async)
4+
[![License](https://img.shields.io/npm/l/react-router-async.svg?style=flat-square)](https://www.npmjs.com/package/react-router-async)
5+
6+
``IMPORTANT NOTE! STATUS FOR THIS PROJECT IS EXPERIMENTAL AND THINGS CAN CHANGE, IT'S NOT READY FOR PRODUCTION``
7+
8+
React Router Async is ultimate routing solution for your React applications, especially it's good in universal applications.
9+
10+
## Installation
11+
```bash
12+
yarn add react-router-async
13+
```
14+
15+
## Usage
16+
On client:
17+
```javascript
18+
import React from 'react';
19+
import ReactDOM from 'react-dom';
20+
import { Router } from 'react-router-async';
21+
import { routes, hooks } from './common';
22+
import createHistory from 'history/createBrowserHistory';
23+
24+
const history = createHistory();
25+
const mountNode = document.getElementById('app');
26+
27+
Router.init({ path: history.location.pathname, routes, hooks }).then(({ Router, Component, router, callback }) => {
28+
ReactDOM.render(<Router {...{ Component, router, history }} />, mountNode, callback);
29+
}).catch(error => console.log(error));
30+
```
31+
32+
On server (for example as express middleware):
33+
```javascript
34+
export default function (req, res, next) {
35+
Router.init({ path: req.path, routes, hooks }).then(({ Component, status, redirect }) => {
36+
if (redirect) {
37+
res.redirect(status, redirect);
38+
} else {
39+
const html = ReactDOM.renderToStaticMarkup(HtmlComponent({
40+
markup: ReactDOM.renderToString(<Component />),
41+
assets: assets
42+
}));
43+
res.status(status).send('<!DOCTYPE html>' + html);
44+
}
45+
}).catch(error => {
46+
if (error.name === 'RouterError') {
47+
res.status(error.code).send(error.message);
48+
} else {
49+
res.status(500).send('Internal error');
50+
}
51+
});
52+
}
53+
```
54+

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-router-async",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"author": {
55
"name": "Oleg Martynov",
66
"email": "[email protected]"
@@ -23,5 +23,9 @@
2323
},
2424
"devDependencies": {
2525
"typescript": "next"
26+
},
27+
"dependencies": {
28+
"react": "^15.3.2",
29+
"router-async": "0.0.2"
2630
}
27-
}
31+
}

src/helpers.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const jsxInstanceOf = cls => {
2+
return (props, propName, componentName) => {
3+
if (props[propName].type !== cls.default) {
4+
return new Error(
5+
'Invalid prop `' + propName + '` supplied to' +
6+
' `' + componentName + '`. Validation failed.'
7+
);
8+
}
9+
}
10+
};
11+
12+
export function deepMap(arr, f, ctx = null) {
13+
return arr.map((val, key) => {
14+
let obj = f.call(ctx, val, key);
15+
if (Array.isArray(obj.childs)) {
16+
obj.childs = deepMap(obj.childs, f, ctx);
17+
return obj;
18+
} else {
19+
return obj;
20+
}
21+
})
22+
}

src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
console.log('nooooop');
1+
import Router from './router';
2+
import Route from './route';
3+
import Link from './link';
4+
import RootRoute from './root-route';
5+
import Middleware from './middleware';
6+
import Redirect from './redirect';
7+
8+
export { Router, Route, Link, RootRoute, Middleware, Redirect };

src/link.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
3+
export interface Props {
4+
to: any,
5+
[propName: string]: any;
6+
}
7+
export interface State {
8+
[propName: string]: any;
9+
}
10+
11+
export default class Link extends React.Component<Props, State> {
12+
context: any;
13+
static contextTypes = {
14+
router: React.PropTypes.object
15+
};
16+
navigate = e => {
17+
this.context.router.navigate(this.props.to);
18+
e.preventDefault();
19+
};
20+
render() {
21+
return <a href={this.props.to} onClick={this.navigate}>{this.props.children}</a>;
22+
}
23+
}

src/middleware.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from 'react';
2+
import { jsxInstanceOf } from './helpers';
3+
import * as Route from './route';
4+
import * as Redirect from './redirect';
5+
6+
export interface Props {
7+
[propName: string]: any;
8+
}
9+
export interface State {
10+
[propName: string]: any;
11+
}
12+
13+
export default class Middleware extends React.Component<Props, State> {
14+
static propTypes = {
15+
children: React.PropTypes.arrayOf(React.PropTypes.oneOfType([
16+
jsxInstanceOf(Route),
17+
jsxInstanceOf(Redirect)
18+
])).isRequired,
19+
path: React.PropTypes.string.isRequired,
20+
action: React.PropTypes.func
21+
};
22+
render() {
23+
return React.Children.only(this.props.children);
24+
}
25+
}

src/redirect.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
3+
export interface Props {
4+
[propName: string]: any;
5+
}
6+
export interface State {
7+
[propName: string]: any;
8+
}
9+
10+
export default class Redirect extends React.Component<Props, State> {
11+
static propTypes = {
12+
path: React.PropTypes.string.isRequired,
13+
to: React.PropTypes.string.isRequired,
14+
status: React.PropTypes.oneOf([301, 302])
15+
};
16+
static defaultProps = {
17+
status: 302
18+
};
19+
render() {
20+
console.error('Redirect can\'t render');
21+
return null;
22+
}
23+
}

src/root-route.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from 'react';
2+
import { jsxInstanceOf } from './helpers';
3+
import * as Route from './route';
4+
import * as Middleware from './middleware';
5+
import * as Redirect from './redirect';
6+
7+
export interface Props {
8+
[propName: string]: any;
9+
}
10+
export interface State {
11+
[propName: string]: any;
12+
}
13+
14+
export default class RootRoute extends React.Component<Props, State> {
15+
static propTypes = {
16+
children: React.PropTypes.arrayOf(React.PropTypes.oneOfType([
17+
jsxInstanceOf(Route),
18+
jsxInstanceOf(Middleware),
19+
jsxInstanceOf(Redirect)
20+
])).isRequired
21+
};
22+
render() {
23+
return React.Children.only(this.props.children);
24+
}
25+
}

src/route.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import * as React from 'react';
2+
3+
export interface Props {
4+
[propName: string]: any;
5+
}
6+
export interface State {
7+
[propName: string]: any;
8+
}
9+
10+
export default class Route extends React.Component<Props, State> {
11+
static propTypes = {
12+
path: React.PropTypes.string.isRequired,
13+
action: React.PropTypes.func.isRequired,
14+
status: React.PropTypes.oneOf([200, 404, 500])
15+
};
16+
render() {
17+
console.error('Route can\'t render');
18+
return null;
19+
}
20+
}

0 commit comments

Comments
 (0)