|
| 1 | +## [HEAD] |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +## [v1.0.0] |
| 6 | + |
| 7 | +Thanks for your patience :) Big changes from v0.13.x to 1.0. While on |
| 8 | +the surface a lot of this just looks like shuffling around API, the |
| 9 | +entire codebase has been rewritten to handle some really great use |
| 10 | +cases, like loading routes and components on demand, session-based route |
| 11 | +matching, server rendering, integration with libs like redux and relay, |
| 12 | +and lots more. |
| 13 | + |
| 14 | +But for now, here's how to translate the old API to the new one. |
| 15 | + |
| 16 | +### Importing |
| 17 | + |
| 18 | +The new `Router` component is a property of the top-level module. |
| 19 | + |
| 20 | +```js |
| 21 | +// v0.13.x |
| 22 | +var Router = require('react-router'); |
| 23 | +var Route = Router.Route; |
| 24 | + |
| 25 | +// v1.0 |
| 26 | +var ReactRouter = require('react-router'); |
| 27 | +var Router = ReactRouter.Router; |
| 28 | +var Route = ReactRouter.Route; |
| 29 | + |
| 30 | +// or using ES Modules |
| 31 | +import { Router, Route } from 'react-router'; |
| 32 | +``` |
| 33 | + |
| 34 | +### Rendering |
| 35 | + |
| 36 | +```js |
| 37 | +// v0.13.x |
| 38 | +Router.run(routes, (Handler) => { |
| 39 | + render(<Handler/>, el); |
| 40 | +}) |
| 41 | + |
| 42 | +// v1.0 |
| 43 | +render(<Router>{routes}</Router>, el) |
| 44 | + |
| 45 | +// looks more like this: |
| 46 | +render(( |
| 47 | + <Router> |
| 48 | + <Route path="/" component={App}/> |
| 49 | + </Router> |
| 50 | +), el); |
| 51 | + |
| 52 | +// or if you'd rather |
| 53 | +render(<Router routes={routes}/>, el) |
| 54 | +``` |
| 55 | + |
| 56 | +### Locations |
| 57 | + |
| 58 | +Locations are now called histories (that emit locations). You import |
| 59 | +them from the [`history` package](https://github.com/rackt/history), not react router. |
| 60 | + |
| 61 | +```js |
| 62 | +// v0.13.x |
| 63 | +Router.run(routes, Router.BrowserHistory, (Handler) => { |
| 64 | + render(<Handler/>, el); |
| 65 | +}) |
| 66 | + |
| 67 | +// v1.0 |
| 68 | +import createBrowserHistory from 'history/lib/createBrowserHistory' |
| 69 | +let history = createBrowserHistory() |
| 70 | +render(<Router history={history}>{routes}</Router>, el) |
| 71 | +``` |
| 72 | + |
| 73 | +If you do not specify a history type (as in the example above) then you will notice some unusual behaviour after updating to 1.0.0. With the default hash based routing a querystring entry not defined by yourself will start appearing in your URLs called `_k`. An example of how it looks is this: `?_k=umhx1s` |
| 74 | + |
| 75 | +This is intended and part of [createHashHistory](https://github.com/rackt/react-router/blob/master/docs/guides/basics/Histories.md#createhashhistory) (which is the default history approach used if one is not specified). You can read more about the feature [here](https://github.com/rackt/react-router/blob/master/docs/guides/basics/Histories.md#what-is-that-_kckuvup-junk-in-the-url) and how to opt out [here](https://rackt.github.io/history/stable/HashHistoryCaveats.html). |
| 76 | + |
| 77 | +### Route Config |
| 78 | + |
| 79 | +You can still nest your routes as before, paths are inherited from |
| 80 | +parents just like before but prop names have changed. |
| 81 | + |
| 82 | +```js |
| 83 | +// v0.13.x |
| 84 | +<Route name="about" handler={About}/> |
| 85 | + |
| 86 | +// v1.0 |
| 87 | +<Route path="about" component={About}/> |
| 88 | +``` |
| 89 | + |
| 90 | +Named routes are gone (for now, [see discussion](https://github.com/rackt/react-router/issues/1840)) |
| 91 | + |
| 92 | +### NotFound route |
| 93 | + |
| 94 | +Not found really confused people, mistaking not finding resources |
| 95 | +from your API for not matching a route. We've removed it completely |
| 96 | +since it's simple with a `*` path. |
| 97 | + |
| 98 | +```js |
| 99 | +// v0.13.x |
| 100 | +<NotFoundRoute handler={NoMatch}/> |
| 101 | + |
| 102 | +// v1.0 |
| 103 | +<Route path="*" component={NoMatch}/> |
| 104 | +``` |
| 105 | + |
| 106 | +### Redirect route |
| 107 | + |
| 108 | +```js |
| 109 | +// v0.13.x |
| 110 | +<Redirect from="some/where/:id" to="somewhere/else/:id" params={{id: 2}}/> |
| 111 | + |
| 112 | +// v1.0 |
| 113 | +// Works the same as before, except no params, just put them in the path |
| 114 | +<Redirect from="/some/where/:id" to="/somewhere/else/2"/> |
| 115 | +``` |
| 116 | + |
| 117 | +### Links |
| 118 | + |
| 119 | +#### path / params |
| 120 | + |
| 121 | +```js |
| 122 | +// v0.13.x |
| 123 | +<Link to="user" params={{userId: user.id}}>Mateusz</Link> |
| 124 | + |
| 125 | +// v1.0 |
| 126 | +// because named routes are gone, link to full paths, you no longer need |
| 127 | +// to know the names of the parameters, and string templates are quite |
| 128 | +// nice. Note that `query` has not changed. |
| 129 | +<Link to={`/users/${user.id}`}>Mateusz</Link> |
| 130 | +``` |
| 131 | + |
| 132 | +#### "active" class |
| 133 | + |
| 134 | +In 0.13.x links added the "active" class by default which you could |
| 135 | +override with `activeClassName`, or provide `activeStyle`s. It's usually |
| 136 | +just a handful of navigation links that need this behavior. |
| 137 | + |
| 138 | +Links no longer add the "active" class by default (its expensive and |
| 139 | +usually not necessary), you opt-in by providing one; if no |
| 140 | +`activeClassName` or `activeStyle`s are provided, the link will not |
| 141 | +check if it's active. |
| 142 | + |
| 143 | +```js |
| 144 | +// v0.13.x |
| 145 | +<Link to="about">About</Link> |
| 146 | + |
| 147 | +// v1.0 |
| 148 | +<Link to="/about" activeClassName="active">About</Link> |
| 149 | +``` |
| 150 | + |
| 151 | +#### Linking to Index routes |
| 152 | + |
| 153 | +Because named routes are gone, a link to `/` with an index route at `/` |
| 154 | +will always be active. So we've introduced `IndexLink` that is only |
| 155 | +active when on exactly that path. |
| 156 | + |
| 157 | +```js |
| 158 | +// v0.13.x |
| 159 | +// with this route config |
| 160 | +<Route path="/" handler={App}> |
| 161 | + <DefaultRoute name="home" handler={Home}/> |
| 162 | + <Route name="about" handler={About}/> |
| 163 | +</Route> |
| 164 | + |
| 165 | +// will be active only when home is active, not when about is active |
| 166 | +<Link to="home">Home</Link> |
| 167 | + |
| 168 | +// v1.0 |
| 169 | +<Route path="/" component={App}> |
| 170 | + <IndexRoute component={Home}/> |
| 171 | + <Route path="about" component={About}/> |
| 172 | +</Route> |
| 173 | + |
| 174 | +// will be active only when home is active, not when about is active |
| 175 | +<IndexLink to="/">Home</IndexLink> |
| 176 | +``` |
| 177 | + |
| 178 | +This gives you more granular control of what causes a link to be active |
| 179 | +or not when there is an index route involved. |
| 180 | + |
| 181 | +#### onClick handler |
| 182 | + |
| 183 | +For consistency with React v0.14, returning `false` from a `Link`'s `onClick` |
| 184 | +handler no longer prevents the transition. To prevent the transition, call |
| 185 | +`e.preventDefault()` instead. |
| 186 | + |
| 187 | +### RouteHandler |
| 188 | + |
| 189 | +`RouteHandler` is gone. `Router` now automatically populates |
| 190 | +`this.props.children` of your components based on the active route. |
| 191 | + |
| 192 | +```js |
| 193 | +// v0.13.x |
| 194 | +<RouteHandler/> |
| 195 | +<RouteHandler someExtraProp={something}/> |
| 196 | + |
| 197 | +// v1.0 |
| 198 | +{this.props.children} |
| 199 | +{React.cloneElement(this.props.children, {someExtraProp: something})} |
| 200 | +``` |
| 201 | + |
| 202 | +**Note:** React does not validate `propTypes` that are specified via `cloneElement` (see: [facebook/react#4494](https://github.com/facebook/react/issues/4494#issuecomment-125068868)). It is recommended to make such `propTypes` optional. |
| 203 | + |
| 204 | +### Navigation Mixin |
| 205 | + |
| 206 | +If you were using the `Navigation` mixin, use the `History` mixin instead. |
| 207 | + |
| 208 | +```js |
| 209 | +// v0.13.x |
| 210 | +var Assignment = React.createClass({ |
| 211 | + mixins: [ Navigation ], |
| 212 | + navigateAfterSomethingHappened () { |
| 213 | + this.transitionTo('/users', { userId: user.id }, query); |
| 214 | + // this.replaceWith('/users', { userId: user.id }, query); |
| 215 | + } |
| 216 | +}) |
| 217 | + |
| 218 | +// v1.0 |
| 219 | +var Assignment = React.createClass({ |
| 220 | + mixins: [ History ], |
| 221 | + navigateAfterSomethingHappened () { |
| 222 | + // the router is now built on rackt/history, and it is a first class |
| 223 | + // API in the router for navigating |
| 224 | + this.history.pushState(null, `/users/${user.id}`, query); |
| 225 | + // this.history.replaceState(null, `/users/${user.id}`, query); |
| 226 | + } |
| 227 | +}) |
| 228 | +``` |
| 229 | + |
| 230 | +The following `Navigation` methods are now also found on the history |
| 231 | +object, main difference again is there are no params or route names, |
| 232 | +just pathnames. |
| 233 | + |
| 234 | +| v0.13 | v1.0 | |
| 235 | +|--------------------------------------|-------------------------------| |
| 236 | +| `go(n)` | `go(n)` | |
| 237 | +| `goBack()` | `goBack()` | |
| 238 | +| `goForward()` | `goForward()` | |
| 239 | +| `makeHref(routeName, params, query)` | `createHref(pathname, query)` | |
| 240 | +| `makePath(routeName, params, query)` | `createPath(pathname, query)` | |
| 241 | + |
| 242 | +### State mixin |
| 243 | + |
| 244 | +```js |
| 245 | +// v0.13.x |
| 246 | +var Assignment = React.createClass({ |
| 247 | + mixins: [ State ], |
| 248 | + foo () { |
| 249 | + this.getPath() |
| 250 | + this.getParams() |
| 251 | + // etc... |
| 252 | + } |
| 253 | +}) |
| 254 | + |
| 255 | +// v1.0 |
| 256 | +// if you are a route component... |
| 257 | +<Route component={Assignment} /> |
| 258 | + |
| 259 | +var Assignment = React.createClass({ |
| 260 | + foo () { |
| 261 | + this.props.location // contains path information |
| 262 | + this.props.params // contains params |
| 263 | + this.props.history.isActive |
| 264 | + } |
| 265 | +}) |
| 266 | + |
| 267 | +// if you're not a route component, you need to pass location down the |
| 268 | +// tree or get the location from context. We will probably provide a |
| 269 | +// higher order component that will do this for you but haven't yet. |
| 270 | +// see further down for more information on what can be passed down |
| 271 | +// via context |
| 272 | +var Assignment = React.createClass({ |
| 273 | + contextTypes: { |
| 274 | + location: React.PropTypes.object |
| 275 | + }, |
| 276 | + foo () { |
| 277 | + this.context.location |
| 278 | + } |
| 279 | +}) |
| 280 | +``` |
| 281 | + |
| 282 | +Here's a table of where you used to get stuff with the `State` mixin, |
| 283 | +and where you get it now if you're a route component (`this.props`) |
| 284 | + |
| 285 | + |
| 286 | +| v0.13 (this) | v1.0 (this.props) | |
| 287 | +|-------------------|------------------------------------| |
| 288 | +| `getPath()` | `location.pathname+location.search`| |
| 289 | +| `getPathname()` | `location.pathname` | |
| 290 | +| `getParams()` | `params` | |
| 291 | +| `getQuery()` | `location.search` | |
| 292 | +| `getQueryParams()`| `location.query` | |
| 293 | +| `getRoutes()` | `routes` | |
| 294 | +| `isActive(to, params, query)` | `history.isActive(pathname, query, onlyActiveOnIndex)` | |
| 295 | + |
| 296 | +Here is another table of properties you used to get via the `State` and |
| 297 | +where you can get it now if you are **not** a route component |
| 298 | +(`this.context`). |
| 299 | + |
| 300 | +| v0.13 (this) | v1.0 (this.context) | |
| 301 | +|-------------------|------------------------------------| |
| 302 | +| `getPath()` | `location.pathname+location.search`| |
| 303 | +| `getPathname()` | `location.pathname` | |
| 304 | +| `getQuery()` | `location.search` | |
| 305 | +| `getQueryParams()`| `location.query` | |
| 306 | +| `isActive(to, params, query)` | `history.isActive(pathname, query, indexOnly)` | |
| 307 | + |
| 308 | +Note not all `State` functionality can be accessed via context in v1.0. |
| 309 | +For example, `params` is not available via context. |
| 310 | + |
| 311 | +### Scrolling |
| 312 | + |
| 313 | +We're developing scroll behaviors separately in the |
| 314 | +[`scroll-behavior`](https://github.com/rackt/scroll-behavior) |
| 315 | +library until we have a stable, robust implementation that we're happy with. |
| 316 | +Currently, scroll behaviors are exposed there as history enhancers: |
| 317 | + |
| 318 | +```js |
| 319 | +import createHistory from 'history/lib/createBrowserHistory' |
| 320 | +import useScroll from 'scroll-behavior/lib/useStandardScroll' |
| 321 | + |
| 322 | +const history = useScroll(createHistory)() |
| 323 | +``` |
| 324 | + |
| 325 | +### `willTransitionTo` and `willTransitionFrom` |
| 326 | + |
| 327 | +Routes now define this behavior: |
| 328 | + |
| 329 | +```js |
| 330 | +// v0.13.x |
| 331 | +var Home = React.createClass({ |
| 332 | + statics: { |
| 333 | + willTransitionTo (transition, params, query, callback) { } |
| 334 | + willTransitionFrom (component, transition, params, query, callback) { } |
| 335 | + } |
| 336 | +}) |
| 337 | + |
| 338 | +// v1.0 |
| 339 | +<Route |
| 340 | + component={Home} |
| 341 | + onEnter={(location, replaceWith) => {}} |
| 342 | + onLeave={() => {}} |
| 343 | +/> |
| 344 | +``` |
| 345 | + |
| 346 | +To cancel a "transition from", please refer to the |
| 347 | +[Confirming Navigation](docs/guides/advanced/ConfirmingNavigation.md) guide. |
| 348 | + |
| 349 | +### We'll keep updating this |
| 350 | + |
| 351 | +There's a lot of the old API we've missed, please give the [new |
| 352 | +docs](/docs) a read and help us fill this guide in. Thanks! |
| 353 | + |
| 354 | + |
0 commit comments