1 | ## rrc = react router components
|
2 |
|
3 | [![Travis][build-badge]][build]
|
4 |
|
5 | [build-badge]: https://img.shields.io/travis/pshrmn/rrc/master.svg?style=flat-square
|
6 | [build]: https://travis-ci.org/pshrmn/rrc
|
7 |
|
8 | This module contains a number of components that can be used in conjuction with [React Router v4](https://github.com/ReactTraining/react-router/tree/master). They are a somewhat random assortment of solutions to situations that I have either personally needed a component for or have seen others need a component for.
|
9 |
|
10 | ### Installation
|
11 |
|
12 | ```
|
13 | npm install --save rrc
|
14 | ```
|
15 |
|
16 | #### UMD
|
17 |
|
18 | You can also use the UMD version of `rrc`. This is useful if you are putting together a code snippet.
|
19 |
|
20 | ```html
|
21 | <script src="https://unpkg.com/rrc@0.10.0/umd/rrc.min.js"></script>
|
22 | ```
|
23 |
|
24 | **Note:** The UMD builds are slightly bloated because they have to include React Router's `<Route>` component and `matchPath` function. This is because if you use the UMD build of `react-router-dom` instead of `react-router`, the `ReactRouter` global will not exist and `rrc`'s imports will fail. The bloat is less than the extra data required to download the `react-router` build and this approach requires one less `<script>` tag.
|
25 |
|
26 | ### Components
|
27 |
|
28 | Read about the various components that are provided in the [docs](docs/README.md)
|
29 |
|
30 | These include:
|
31 |
|
32 | #### `<ConfigSwitch>` and `wrapSwitch`
|
33 |
|
34 | These both provide an alternative approach to React Router's `<Switch>` component. Intead of passing child elements to the `<Switch>`, both `<ConfigSwitch>` and the component returned by the `wrapSwitch` HOC take an array of route objects via the `routes` prop.
|
35 |
|
36 | ```js
|
37 | <ConfigSwitch routes={[
|
38 | { path: '/', exact: true, component: Home },
|
39 | { path: '/about' component: About }
|
40 | ]}/>
|
41 | ```
|
42 |
|
43 | `wrapSwitch` in particular is useful for animations. It allows you to specify a component that will be used to wrap the matched route, providing better support for nested animations than is available with `<Switch>`
|
44 |
|
45 | ```js
|
46 | import { CSSTransitionGroup } from 'react-transition-group'
|
47 |
|
48 | const CSSSwitch = wrapSwitch(CSSTransitionGroup)
|
49 |
|
50 | const App = () => (
|
51 | <CSSSwitch
|
52 | transitionName='slide'
|
53 | component='div'
|
54 | routes={[
|
55 | { path: '/', exact: true, component: Home },
|
56 | { path: '/about' component: About }
|
57 | ]}
|
58 | />
|
59 | )
|
60 | ```
|
61 |
|
62 | #### `<Status>`
|
63 |
|
64 | If you are doing server side rendering, the `<Status>` component offers an easy way to "render" a status. For example, if you have a "404" component that renders when no routes match, you can include a `<Status>` element inside of its render method so that your server can send the correct status code with the response.
|
65 |
|
66 | ```js
|
67 | const NoMatch = () => (
|
68 | <div>
|
69 | <Status code='404' />
|
70 | <h1>404</h1>
|
71 | <p>The page you were looking for was not found</p>
|
72 | </div>
|
73 | )
|
74 | ```
|
75 |
|
76 | The `<Status>` component will set a property on the `context` object that you pass to the `<StaticRouter>`, so all that you have to do is check the context object's `status` property.
|
77 |
|
78 | ```js
|
79 | const context = {}
|
80 | const markup = renderToString(
|
81 | <StaticRouter context={context}>
|
82 | <App />
|
83 | </StaticRouter>
|
84 | )
|
85 |
|
86 | if (context.status === '404') {
|
87 | // ...
|
88 | }
|
89 | ```
|
90 |
|
91 | #### `whenActive`
|
92 |
|
93 | The `whenActive` higher-order component creates `<NavLink>`-like components. While a `<NavLink>` can only create `<a>`s, the component returned by `whenActive` can render anything that you'd like.
|
94 |
|
95 | ```js
|
96 | // a button that can navigate
|
97 | const Button = ({ to, ...rest}, { router }) => (
|
98 | <button
|
99 | type='button'
|
100 | onClick={(e) => {
|
101 | e.preventDefault()
|
102 | router.history.push(to)
|
103 | }}
|
104 | {...rest}
|
105 | />
|
106 | )
|
107 |
|
108 | const ActiveButton = whenActive({ className: 'i-am-active' })(Button)
|
109 |
|
110 | // usage
|
111 | const Controls = () => (
|
112 | <div>
|
113 | <ActiveButton to='/'>Home</ActiveButton>
|
114 | <ActiveButton to='/form'>Form</ActiveButton>
|
115 | </div>
|
116 | )
|
117 | ```
|
118 |
|
119 | This can also be used in place of the `<NavLink>` so that you don't have to specify the same "active" props for every location-aware link.
|
120 |
|
121 | ```js
|
122 | // with NavLink
|
123 | const Links = () => (
|
124 | <div>
|
125 | <NavLink to='/one' activeClassName='the-active-class'>One</NavLink>
|
126 | <NavLink to='/two' activeClassName='the-active-class'>Two</NavLink>
|
127 | <NavLink to='/three' activeClassName='the-active-class'>Three</NavLink>
|
128 | </div>
|
129 | )
|
130 |
|
131 | // with whenActive
|
132 | const ActiveLink = whenActive({ className: 'the-active-class' })(Link)
|
133 | const Links = () => (
|
134 | <div>
|
135 | <ActiveLink to='/one'>One</ActiveLink>
|
136 | <ActiveLink to='/two'>Two</ActiveLink>
|
137 | <ActiveLink to='/three'>Three</ActiveLink>
|
138 | </div>
|
139 | )
|
140 | ```
|
141 |
|
142 | ### Related Projects:
|
143 |
|
144 | * [`qhistory`](https://github.com/pshrmn/qhistory) - Add query object support to location objects
|
145 | * [`react-router-test-context`](https://github.com/pshrmn/react-router-test-context) - Simulate the `context.router` object. This can be useful if you are doing shallow testing of a component that needs to access React Router's context variables. Typically, though, you should just render your component inside of a `<MemoryRouter>`.
|