Skip to content

Commit

Permalink
feat(routeNode): Inject route (observable) and plainRoute (non-observ…
Browse files Browse the repository at this point in the history
…able) to wrapped component

For consistency with other HOCs of this package I renamed back the injected current route as simply
`route`. Additionally now this component injects also a plain non-observable route called
`plainRoute` to satisfy all possible use-cases.

BREAKING CHANGE: RouteNode HOC previous injected activeRoute is now called route (observable). An
non-observable version is also injected and called `plainRoute`.
  • Loading branch information
LeonardoGentile committed Jun 19, 2017
1 parent 5f7fa23 commit 8d6ca7d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 48 deletions.
89 changes: 45 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ The final usage would be:
The newly created `RouteNodeInstance` HOC is a *wrapper* around `RouteComponent` and will:

- forward all the props received to the wrapped `RouteComponent`
- inject the `activeRoute` (non-observable) and `routerStore` props to the `RouteComponent`
- inject the `route` (observable), `plainRoute` (non-observable) and `routerStore` props to the `RouteComponent`
- trigger a re-rendering of itself and of the wrapped `RouteComponent` only **when** the **nodeName** is the correct **intersection node** for the current route transition (see [understanding router5](http://router5.github.io/docs/understanding-router5.html) and the example below).


Expand Down Expand Up @@ -199,10 +199,10 @@ import { routeNode } from 'react-mobx-router5';
import { UserView, UserList, NotFound } from './components';

function UsersComp(props) {
// These are injected by routeNode HOC
const { routerStore, activeRoute } = props;
// These are injected by routeNode HOC
const { routerStore, route, plainRoute } = props;

switch (activeRoute.name) {
switch (route.name) {
case 'users.detail':
return <UserDetail/>;
case 'users.view':
Expand Down Expand Up @@ -277,7 +277,7 @@ export default [

Notice that the component associated with a route node (the ones having children, for example `Sections`) should already be wrapped with `routeNode`. In other words the `Sections` component should be exported like this:

```
```javascript
export default routeNode('section')(Sections);
```

Expand Down Expand Up @@ -317,14 +317,14 @@ import routes from "../../routes";

class Main extends React.Component {
render(){
// injected by routeNode HOC
const { routerStore, activeRoute } = this.props;
// injected by routeNode HOC
const { routerStore, route, plainRoute } = this.props;

// This will extract the correct component amongst the children of '' for the current route
// Notice that the ComponentToRender could also be another routeNode, for example `Section`
const ComponentToRender = getComponent(activeRoute, '', routes);
// Passing the activeRoute prop will ensure that the ComponentToRender will be re-rendered for each new route
return createElement(ComponentToRender, {route: activeRoute});
const ComponentToRender = getComponent(route, '', routes);
// Passing the route prop will ensure that the ComponentToRender will be re-rendered for each new route
return createElement(ComponentToRender, {route: route});
}
}

Expand All @@ -341,13 +341,13 @@ import routes from "../../routes";

class Section extends React.Component {
render(){
// injected by routeNode HOC
const { activeRoute, routerStore } = this.props;
// injected by routeNode HOC
const { route, routerStore, plainRoute } = this.props;

// This will extract the correct component amongst the children of 'section' for the current route
// Notice that the ComponentToRender could also be another routeNode, for example `Subsection`
const ComponentToRender = getComponent(activeRoute, 'section', routes);
return createElement(ComponentToRender, {route: activeRoute});
const ComponentToRender = getComponent(route, 'section', routes);
return createElement(ComponentToRender, {route: route});
}
}

Expand All @@ -359,9 +359,9 @@ export default routeNode('section')(Section);

The `getComponent` solution introduces some repetition, that is, you always need to grab the component to render and then render it:

```
const ComponentToRender = getComponent(activeRoute, 'section', routes);
return createElement(ComponentToRender, {route: activeRoute});
```javascript
const ComponentToRender = getComponent(route, 'section', routes);
return createElement(ComponentToRender, {route: route});
```

The `RouteView` component does these two operations for you.
Expand All @@ -374,13 +374,14 @@ All props not listed below will be passed trough to the new generated component

**Props**

- `route`: a route object (**required**). Better to use the **non-observable** `activeRoute` injected by `routeNode` rather than `routerStore.route` to avoid possible inconsistencies.
- `route`: a route object (**required**). It **might** be better to pass the **non-observable** `plainRoute` injected by `routeNode` rather than `routerStore.route`
to avoid possible inconsistencies if the subcomponents are observers of `route` (**TODO**: This use case needs more study)
- `routeNodeName`: the name of the route for the React component from where to re-render (route node)
- `routes`: nested routes configuration array (with the extra `component` field for each route)

**Example**

```
```javascript
//Main.jsx: the root routeNode ('')
import React, {createElement} from "react";
import {routeNode, RouteView} from "react-mobx-router5";
Expand All @@ -390,14 +391,14 @@ const routeNodeName = '';

class Main extends React.Component {
render(){
const {activeRoute, routerStore} = this.props;
return <RouteView
route={activeRoute}
routeNodeName={routeNodeName}
routes={routes}
// other props
otherProp='hello'
myOtherProp='bye' />;
const {route, routerStore} = this.props;
return <RouteView
route={route}
routeNodeName={routeNodeName}
routes={routes}
// other props
otherProp='hello'
myOtherProp='bye' />;
}
}

Expand Down Expand Up @@ -475,15 +476,15 @@ import React from 'react';
import { withRoute } from 'react-mobx-router5';

function MyComp(props) {
// these are injected by withRoute
const { route, isActive, className } = props;
return (
<div className={className}>
I am {isActive: 'active' ? 'inactive' } <br/>
The current route is {route}
</div>
)
// these are injected by withRoute
const { route, isActive, className } = props;
return (
<div className={className}>
I am {isActive: 'active' ? 'inactive' } <br/>
The current route is {route}
</div>
)

}
export default withRoute(MyComp);
Expand All @@ -495,14 +496,14 @@ import React from 'react';
import MyComp from './MyComp';

function Container(props) {
return (
<div>
<MyComp
routeName='home'
className='hello'
activeClassName='hyperactive' />
</div>
)
return (
<div>
<MyComp
routeName='home'
className='hello'
activeClassName='hyperactive' />
</div>
)

}
export default Container;
Expand Down
4 changes: 2 additions & 2 deletions src/modules/routeNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ function routeNode(nodeName, storeName = 'routerStore') { // route node Name, ro

render() {
const {route} = this.state;
const activeRoute = toJS(route); // convert to plain object
return createElement(RouteComponent, {...this.props, [storeName]: this.props[storeName], activeRoute});
const plainRoute = toJS(route); // convert to plain object
return createElement(RouteComponent, {...this.props, [storeName]: this.props[storeName], route, plainRoute});
}
}

Expand Down
5 changes: 3 additions & 2 deletions test/routeNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('routeNode hoc', () => {

context('Wrapped component (RouteComponent)', function () {

it('should receive props: `routerStore`, `activeRoute` (non-observable) ', () => {
it('should receive props: `routerStore`, `route`(observable) and `plainRoute` (non-observable) ', () => {
const SegmentCompSpy= spy(FnComp);
NodeComp = routeNode('')(SegmentCompSpy);
router.addNode('home', '/home');
Expand All @@ -77,7 +77,8 @@ describe('routeNode hoc', () => {
expect(SegmentCompSpy).to.have.been.calledWithMatch(
{
routerStore: routerStore,
activeRoute: router.getState(),
route: routerStore.route,
plainRoute: router.getState()
}
);
});
Expand Down

0 comments on commit 8d6ca7d

Please sign in to comment.