Skip to content

Commit

Permalink
Work around React Hot Loader proxying route classes
Browse files Browse the repository at this point in the history
  • Loading branch information
taion committed Nov 3, 2017
1 parent 52917b8 commit dbfc6b8
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 1 deletion.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,27 @@ const route = {
};
```

#### Custom route classes

You can implement reusable logic in routes with a custom route class. When extending `Route`, methods defined on the class will be overridden by explicitly specified route properties. You can use custom route classes for either object route configurations or JSX route configurations.

> **Note:** To avoid issues with [React Hot Loader](http://gaearon.github.io/react-hot-loader/), custom route classes should usually extend `Route`.
```js
class AsyncRoute extends Route {
// An explicit render property on the route will override this.
render({ Component, props }) {
return Component && props ? (
<Component {...props} />
) : (
<LoadingIndicator />
);
}

const myRoute = new AsyncRoute(properties);
const myJsxRoute = <AsyncRoute {...properties} />;
```
### Router configuration
Found exposes a number of router component class factories at varying levels of abstraction. These factories accept the static configuration properties for the router, such as the route configuration. The use of static configuration allows for efficient, parallel data fetching and state management as above.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"jest": "^21.1.0",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-proxy": "^3.0.0-alpha.1",
"react-test-renderer": "^15.6.1",
"rimraf": "^2.6.2"
}
Expand Down
6 changes: 6 additions & 0 deletions src/Redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ export default class Redirect {
throw new RedirectException(toLocation);
}
}

if (__DEV__) {
// Workaround to make React Proxy give me the original class, to allow
// makeRouteConfig to get the actual class, when using JSX for routes.
Redirect.prototype.isReactComponent = {};
}
6 changes: 6 additions & 0 deletions src/Route.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ export default class Route {
Object.assign(this, props);
}
}

if (__DEV__) {
// Workaround to make React Proxy give me the original class, to allow
// makeRouteConfig to get the actual class, when using JSX for routes.
Route.prototype.isReactComponent = {};
}
7 changes: 7 additions & 0 deletions src/makeRouteConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ export default function makeRouteConfig(node) {
return React.Children.toArray(node)
.filter(React.isValidElement)
.map(({ type: Type, props: { children, ...props } }) => {
if (__DEV__ && Type.prototype.constructor !== Type) {
// With React Hot Loader, this might actually be a proxy. We're not
// actually rendering this and we want the real class instead. This
// isn't a problem here, but can come when users extend route classes.
Type = Type.prototype.constructor; // eslint-disable-line no-param-reassign
}

const route = new Type(props);

if (children) {
Expand Down
11 changes: 11 additions & 0 deletions test/makeRouteConfig.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import createProxy from 'react-proxy';

import makeRouteConfig from '../src/makeRouteConfig';
import Redirect from '../src/Redirect';
Expand Down Expand Up @@ -153,4 +154,14 @@ describe('makeRouteConfig', () => {
],
}]);
});

it('should work with proxies', () => {
const ProxiedRoute = createProxy(Route).get();
const route = makeRouteConfig(
<ProxiedRoute name="foo" path="/" />,
)[0];

// instanceof is not sufficient here, as we want to check the actual class.
expect(Object.getPrototypeOf(route)).toBe(Route.prototype);
});
});
8 changes: 7 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2800,7 +2800,7 @@ lodash.some@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"

lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"

Expand Down Expand Up @@ -3318,6 +3318,12 @@ react-dom@^15.6.1:
object-assign "^4.1.0"
prop-types "^15.5.10"

react-proxy@^3.0.0-alpha.1:
version "3.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07"
dependencies:
lodash "^4.6.1"

react-redux@^5.0.5:
version "5.0.6"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946"
Expand Down

0 comments on commit dbfc6b8

Please sign in to comment.