diff options
Diffstat (limited to 'web/src/vendor/react-router/docs')
15 files changed, 1319 insertions, 0 deletions
diff --git a/web/src/vendor/react-router/docs/api/README.md b/web/src/vendor/react-router/docs/api/README.md new file mode 100644 index 00000000..83c33fba --- /dev/null +++ b/web/src/vendor/react-router/docs/api/README.md @@ -0,0 +1,32 @@ +React Router API +================ + +- [`Router`](/docs/api/Router.md) + +- Components + - [`DefaultRoute`](/docs/api/components/DefaultRoute.md) + - [`Link`](/docs/api/components/Link.md) + - [`NotFoundRoute`](/docs/api/components/NotFoundRoute.md) + - [`Redirect`](/docs/api/components/Redirect.md) + - [`Route`](/docs/api/components/Route.md) + - [`RouteHandler`](/docs/api/components/RouteHandler.md) + - [`Routes`](/docs/api/components/Routes.md) + +- Misc + - [`transition`](/docs/api/misc/transition.md) + +- Mixins + - [`ActiveState`](/docs/api/mixins/ActiveState.md) + - [`AsyncState`](/docs/api/mixins/AsyncState.md) + + +Public Modules +-------------- + +All modules found at the repository root are considered public. You can +require them conveniently with `var Route = require('react-router/Route');` etc. + +Note that we do not support requiring modules from our `modules` +directory. (No notes in the changelog, no changes to the versioning of +the lib, etc.) + diff --git a/web/src/vendor/react-router/docs/api/Router.md b/web/src/vendor/react-router/docs/api/Router.md new file mode 100644 index 00000000..ff0a32f7 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/Router.md @@ -0,0 +1,65 @@ +API: `Router` +============= + +The main export, `Router`, contains several methods that may be used to +navigate around the application. + +```js +// cjs modules +var Router = require('react-router') + +// or global build +window.ReactRouter +``` + +Methods +------- + +### `transitionTo(routeNameOrPath, [params[, query]])` + +Programmatically transition to a new route. + +#### Examples + +```js +Router.transitionTo('user', {id: 10}, {showAge: true}); +Router.transitionTo('about'); +Router.transitionTo('/users/10?showAge=true'); +``` + +### `replaceWith(routeNameOrPath, [params[, query]])` + +Programmatically replace current route with a new route. Does not add an +entry into the browser history. + +#### Examples + +```js +Router.replaceWith('user', {id: 10}, {showAge: true}); +Router.replaceWith('about'); +Router.replaceWith('/users/10?showAge=true'); +``` + +### `goBack()` + +Programmatically go back to the last route and remove the most recent +entry from the browser history. + +#### Example + +```js +Router.goBack(); +``` + +### `makeHref(routeName, params, query)` + +Creates an `href` to a route. Use this along with `ActiveState` when you +need to build components similar to `Link`. + +#### Example + +```js +// given a route like this: +<Route name="user" path="users/:userId"/> +Router.makeHref('user', {userId: 123}); // "users/123" +``` diff --git a/web/src/vendor/react-router/docs/api/components/DefaultRoute.md b/web/src/vendor/react-router/docs/api/components/DefaultRoute.md new file mode 100644 index 00000000..6607832b --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/DefaultRoute.md @@ -0,0 +1,55 @@ +API: `DefaultRoute` (component) +=============================== + +A route that is active when the parent route's path matches exactly. Or, +in other words, the default child route for a parent. + +Note, this is not a `NotFoundRoute`. It is only active when the parent's +route path is matched exactly. + +Props +----- + +See [Route::props][routeProps] + +Example +------- + +```xml +<Routes> + <Route path="/" handler={App}> + + <!-- + when the url is `/`, this handler will be active, or in other + words, will be `this.props.activeRouteHandler in the `App` handler + --> + <DefaultRoute handler={Home}/> + + <Route name="about" handler={About}/> + <Route name="users" handler={Users}> + <Route name="user" handler={User} path="/user/:id"/> + + <!-- when the url is `/users`, this will be active --> + <DefaultRoute handler={UsersIndex}/> + + </Route> + </Route> +</Routes> +``` + +This is all really just a shortcut for the less intuitive version of the +same functionality: + +```xml +<!-- no path or name on what was previously the "users" route --> +<Route handler={Users}> + <!-- the path moved down to the child --> + <Route name="users-index" path="/users" handler={UsersIndex}/> + <Route name="user" handler={User} path="/user/:id"/> +</Route> +``` + +`DefaultRoute` feels more natural, so you can name and transition to the +parent route. + + [routeProps]:/docs/api/components/Route.md#props diff --git a/web/src/vendor/react-router/docs/api/components/Link.md b/web/src/vendor/react-router/docs/api/components/Link.md new file mode 100644 index 00000000..9c5bfd12 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/Link.md @@ -0,0 +1,71 @@ +API: `Link` (component) +========================= + +Creates an anchor tag that links to a route in the application. Also +gets the `active` class automatically when the route matches. If you +change the path of your route, you don't have to change your links. + +Props +----- + +### `to` + +The name of the route to link to, or a full URL. + +### `params` + +Object, the parameters to fill in the dynamic segments of your route. + +#### Example + +```js +// given a route config like this +<Route name="user" path="/user/:userId"/> + +// create a link with this +<Link to="user" params={{userId: "123"}}/> + +// though, if your user properties match up to the dynamic segements: +<Link to="user" params={user}/> +``` + +### `query` + +Object, Query parameters to add to the link. Access query parameters in +your route handler with `this.props.query`. + +### `activeClassName` + +The className a `Link` receives when it's route is active. Defaults to +`active`. + +### `onClick` + +A custom handler for the click event. Works just like a handler on an `<a>` +tag - calling `e.preventDefault()` or returning `false` will prevent the +transition from firing, while `e.stopPropagation()` will prevent the event +from bubbling. + +### *others* + +You can also pass props you'd like to be on the `<a>` such as a title, id, or className. + +Example +------- + +Given a route like `<Route name="user" path="/users/:userId"/>`: + +```xml +<Link to="user" params={{userId: user.id}} query={{foo: bar}}>{user.name}</Link> +<!-- becomes one of these depending on your router and if the route is +active --> +<a href="/users/123?foo=bar" class="active">Michael</a> +<a href="#/users/123?foo=bar">Michael</a> + +<!-- or if you have the full url already, you can just pass that in --> +<Link to="/users/123?foo=bar">{user.name}</Link> + +<!-- change the activeClassName --> +<Link activeClassName="current" to="user" params={{userId: user.id}}>{user.name}</Link> +``` + diff --git a/web/src/vendor/react-router/docs/api/components/NotFoundRoute.md b/web/src/vendor/react-router/docs/api/components/NotFoundRoute.md new file mode 100644 index 00000000..366c78b4 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/NotFoundRoute.md @@ -0,0 +1,36 @@ +API: `NotFoundRoute` (component) +=============================== + +When a parent's URL partially matches, but none of the children do, a +`NotFoundRoute` will be matched and its handler rendered at any level of +your route/view hierarchy. + +Props +----- + +See [Route::props][routeProps] + +Example +------- + +```xml +<Routes> + <Route path="/" handler={App}> + <Route name="course" path="course/:courseId" handler={Course}> + <Route name="course-dashboard" path="dashboard" /> + + <!-- ie: `/course/123/foo` --> + <NotFoundRoute handler={CourseRouteNotFound} /> + </Route> + + <!-- ie: `/flkjasdf` --> + <NotFoundRoute handler={NotFound} /> + </Route> +</Routes> +``` + +The last `NotFoundRoute` will render inside the `App`, the first will +rendering inside of `Course`. + + [routeProps]:/docs/api/components/Route.md#props + diff --git a/web/src/vendor/react-router/docs/api/components/Redirect.md b/web/src/vendor/react-router/docs/api/components/Redirect.md new file mode 100644 index 00000000..a31222a0 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/Redirect.md @@ -0,0 +1,59 @@ +API: `Redirect` (component) +=========================== + +Configures a redirect for a path in your route declarations. + +Props +----- + +### `from` + +The path you want to redirect from, including dynamic segments. Defaults +to `*` so you can redirect anything not found to somewhere else. + +### `to` + +The `name` of the route you want to redirect to. + +Example +------- + +```xml +<!-- + lets say we want to change from `/profile/123` to `/about/123` + and redirect `/get-in-touch` to `/contact` +--> +<Routes> + <Route handler={App}> + <Route name="contact" handler={Contact}/> + <Route name="about-user" path="about/:userId" handler={UserProfile}/> + <Route name="course" path="course/:courseId"> + <Route name="course-dashboard" path="dashboard" handler={Dashboard}/> + <Route name="course-assignments" path="assignments" handler={Assignments}/> + <!-- + anything like `/course/123/invalid` redirects to + `/course/123/dashboard` + --> + <Redirect to="course-dashboard" /> + </Route> + </Route> + + <!-- `/get-in-touch` -> `/contact` --> + <Redirect from="get-in-touch" to="contact" /> + <!-- `/profile/123` -> `/about/123` --> + <Redirect from="profile/:userId" to="about-user" /> +</Routes> +``` + +Note that the `<Redirect/>` can be placed anywhere in the route +hierarchy, if you'd prefer the redirects to be next to their respective +routes. + +```xml +<Routes> + <Route handler={App}> + <Route name="contact" handler={Contact}/> + <Redirect from="get-in-touch" to="contact" /> + </Route> +</Routes> +``` diff --git a/web/src/vendor/react-router/docs/api/components/Route.md b/web/src/vendor/react-router/docs/api/components/Route.md new file mode 100644 index 00000000..b1f3ba9b --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/Route.md @@ -0,0 +1,105 @@ +API: `Route` (component) +========================= + +Configuration component to declare your application's routes and view hierarchy. + +Props +----- + +### `name` + +The name of the route, used in the `Link` component and the router's +transition methods. + +### `path` + +The path used in the URL. If left undefined, the path will be defined by +the `name`, and if there is no name, will default to `/`. + +Please refer to the [Path Matching Guide][path-matching] to learn more +about supported path matching syntax. + +### `handler` + +The component to be rendered when the route is active. + +### `addHandlerKey` + +Defaults to `false`. + +If you have dynamic segments in your URL, a transition from `/users/123` +to `/users/456` does not call `getInitialState`, `componentWillMount` or +`componentWillUnmount`. If you are using those lifecycle hooks to fetch +data and set state, you will also need to implement +`componentWillReceiveProps` on your handler, just like any other +component with changing props. This way, you can leverage the +performance of the React DOM diff algorithm. Look at the `Contact` +handler in the `master-detail` example. + +If you'd rather be lazy, set this to `true` and the router will add a +key to your route, causing all new DOM to be built, and then the life +cycle hooks will all be called. + +You will want this to be `true` if you're doing animations with React's +TransitionGroup component. + +### `preserveScrollPosition` + +If `true`, the router will not scroll the window up when the route is +transitioned to. Defaults to `false`. Ignored if the parent `<Routes/>` +has been set to `true`. + +### `children` + +Routes can be nested. When a child route matches, the parent route's +handler will have the child route's handler available as +`this.props.activeRouteHandler`. You can then render it in the parent +passing in any additional props as needed. + +### `[prop]` + +Any additional, user-defined, properties will be become properties of +the rendered handler. + +#### Example: + +```js +var App; +var foo = "hello"; + +var routes = ( + <Routes> + // pass `foo` to `something` + <Route handler={App} something={foo}/> + </Routes> +); + +App = React.createClass({ + render: function() { + // access `something` on props + return <div>{this.props.something}</div> + } +}); + +React.renderComponent(routes, document.body); +document.body.innerHTML // -> <div>hello</div> +``` + +Example +------- + +```xml +<Routes> + <!-- path defaults to '/' since no name or path provided --> + <Route handler={App}> + <!-- path is automatically assigned to the name since it is omitted --> + <Route name="about" handler={About}/> + <Route name="users" handler={Users}> + <!-- note the dynamic segment in the path --> + <Route name="user" handler={User} path="/user/:id"/> + </Route> + </Route> +</Routes> +``` + + [path-matching]:/docs/guides/path-matching.md diff --git a/web/src/vendor/react-router/docs/api/components/RouteHandler.md b/web/src/vendor/react-router/docs/api/components/RouteHandler.md new file mode 100644 index 00000000..e39fad94 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/RouteHandler.md @@ -0,0 +1,108 @@ +API: `RouteHandler` (component) +=============================== + +The component supplied to a route is called a "Route Handler". They are +rendered when their route is active. There are some special props and +static methods available to these components. + +Props +----- + +### `activeRouteHandler(extraProps)` + +Render the active nested route handler with this property, passing in +additional properties as needed. This is the mechanism by which you get +effortless nested UI. + +#### Example + +```js +var App = React.createClass({ + render: function() { + <div> + <h1>Address Book</h1> + {/* the active child route handler will be rendered here */} + {/* you can "trickle down" props to the active child */} + <this.props.activeRouteHandler someProp="foo" /> + </div> + } +}); + +var Contact = React.createClass({ + render: function() { + return <h1>{this.props.params.id}</h1> + } +}); + +var routes = ( + <Routes> + <Route handler={App}> + <Route name="contact" path="/contact/:id" handler={Contact}> + </Route> + </Routes> +); + +React.renderComponent(routes, document.body); +``` + +### `params` + +When a route has dynamic segments like `<Route path="users/:userId"/>`, +the dynamic values from the url are available at +`this.props.params.userId`, etc. + +### `query` + +The query parameters from the url. + +Static Lifecycle Methods +------------------------ + +You can define static methods on your route handlers that will be called +during route transitions. + +### `willTransitionTo(transition, params, query)` + +Called when a route is about to render, giving you the opportunity to +abort or redirect the transition. You can return a promise and the whole +route hierarchy will wait for the promises to resolve before proceeding. + +See also: [transition](/docs/api/misc/transition.md) + +### `willTransitionFrom(transition, component)` + +Called when an active route is being transitioned out giving you an +opportunity to abort the transition. The `component` is the current +component, you'll probably need it to check its state to decide if you +want to allow the transition. + +See also: [transition](/docs/api/misc/transition.md) + +#### Example + +```js +var Settings = React.createClass({ + statics: { + willTransitionTo: function(transition, params) { + return auth.isLoggedIn().then(function(loggedIn) { + if (!loggedIn) + return; + transition.abort(); + return auth.logIn({transition: transition}); + // in auth module call `transition.retry()` after being logged in + }); + }, + + willTransitionFrom: function(transition, component) { + if (component.formHasUnsavedData())) { + if (!confirm('You have unsaved information, are you sure you want to leave this page?')) { + transition.abort(); + } + } + } + } + + //... +}); +``` + diff --git a/web/src/vendor/react-router/docs/api/components/Routes.md b/web/src/vendor/react-router/docs/api/components/Routes.md new file mode 100644 index 00000000..2d9396aa --- /dev/null +++ b/web/src/vendor/react-router/docs/api/components/Routes.md @@ -0,0 +1,69 @@ +API: `Routes` (component) +========================= + +Configuration component for your router, all `<Route/>`s must be +children of a `<Routes/>`. It is the component you provide to +`React.renderComponent(routes, el)`. + +Props +----- + +### `location` + +One of `"hash"`, `"history"` or a user defined location implementation, +defaults to `"hash"`. + +`"hash"` includes `#/` in the url and works without a server, if you use +`history` your server will need to support it. + +For browsers that don't support the HTML5 history API the router will +fall back to `window.location` if you choose `history`, in other words, +the router will simply cause a full page reload. This way all users get +the same urls and can share them. + +See also: [user supplied locations][Location]. + +### `preserveScrollPosition` + +If `true`, the router will not scroll the window up globally when any +route is transitioned to. Defaults to `false`. When `false`, the +`<Route/>` gets to decide whether or not to scroll on transition. + +### `onAbortedTransition` + +A function called when any transition is aborted. + +### `onActiveStateChange` + +A function called when the active routes change. + +#### signature + +`function(nextState)` + +### `onTransitionError` + +A function called when a transition has an error. + +#### signature + +`function(error)` + +Example +------- + +```jsx +function onError(error) { + handleError(error); +} + +var routes = ( + <Routes location="history" onTransitionError={onError}> + <Route handler={App}/> + </Routes> +); +React.renderComponent(routes, document.body); +``` + + [Location]:../misc/Location.md + diff --git a/web/src/vendor/react-router/docs/api/misc/Location.md b/web/src/vendor/react-router/docs/api/misc/Location.md new file mode 100644 index 00000000..f0b2077b --- /dev/null +++ b/web/src/vendor/react-router/docs/api/misc/Location.md @@ -0,0 +1,66 @@ +API: `Location` (object) +========================== + +You can supply the router with your own location implementation. The +following methods must be implemented: + +Methods +------- + +### `setup(onChange)` + +Called when the router is first setup. Whenever an external actor should +cause the router to react, call `onChange` (for example, on +`window.hashchange`). + +### `teardown` + +Called when the router is torn down. + +### `push` + +Called when the router is transitioning from one path to another. + +### `replace` + +Called when ther router is replacing (not transitioning) one url with +another. + +### `pop` + +Called when the router attempts to go back one entry in the history. + +### `getCurrentPath` + +Should return the current path as a string. + +### `toString` + +Should return a useful string for logging and debugging. + +Example +------- + +This is a terrible example, you're probably better off looking at the +implementations in this repository. + +```js +var MyLocation = { + + setup: function (onChange) {}, + + teardown: function () {}, + + push: function (path) {}, + + replace: function (path) {}, + + pop: function () {}, + + getCurrentPath: function () {}, + + toString: function () {} + +}; +``` + diff --git a/web/src/vendor/react-router/docs/api/misc/transition.md b/web/src/vendor/react-router/docs/api/misc/transition.md new file mode 100644 index 00000000..fc039572 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/misc/transition.md @@ -0,0 +1,24 @@ +API: `transition` (object) +========================== + +This object is sent to the [transition hooks][transition-hooks] as the +first argument. + +Methods +------- + +### `abort()` + +Aborts a transition. + +### `redirect(to, params, query)` + +Redirect to another route. + +### `retry()` + +Retrys a transition. Typically you save off a transition you care to +return to, finish the workflow, then retry. + + [transition-hooks]:/docs/api/components/RouteHandler.md#static-lifecycle-methods + diff --git a/web/src/vendor/react-router/docs/api/mixins/ActiveState.md b/web/src/vendor/react-router/docs/api/mixins/ActiveState.md new file mode 100644 index 00000000..f251bd35 --- /dev/null +++ b/web/src/vendor/react-router/docs/api/mixins/ActiveState.md @@ -0,0 +1,58 @@ +API: `ActiveState` (mixin) +========================== + +A mixin for components that need to know about the routes, params, and +query that are currently active (like links). + +Static Methods +-------------- + +### `isActive(routeName, params, query)` + +Returns `true` if a route, params, and query are active, `false` +otherwise. + +Lifecycle Methods +----------------- + +### `updateActiveState` + +Called when the active state changes. + +Example +------- + +Let's say you are using bootstrap and want to get `active` on those `li` +tags for the Tabs: + +```js +var Link = require('react-router/Link'); +var ActiveState = require('react-router/ActiveState'); + +var Tab = React.createClass({ + + mixins: [ ActiveState ], + + getInitialState: function () { + return { isActive: false }; + }, + + updateActiveState: function () { + this.setState({ + isActive: Tab.isActive(this.props.to, this.props.params, this.props.query) + }) + }, + + render: function() { + var className = this.state.isActive ? 'active' : ''; + var link = Link(this.props); + return <li className={className}>{link}</li>; + } + +}); + +// use it just like <Link/>, and you'll get an anchor wrapped in an `li` +// with an automatic `active` class on both. +<Tab to="foo">Foo</Tab> +``` + diff --git a/web/src/vendor/react-router/docs/api/mixins/AsyncState.md b/web/src/vendor/react-router/docs/api/mixins/AsyncState.md new file mode 100644 index 00000000..e3a40c8c --- /dev/null +++ b/web/src/vendor/react-router/docs/api/mixins/AsyncState.md @@ -0,0 +1,115 @@ +API: `AsyncState` (mixin) +========================= + +A mixin for route handlers that fetch at least part of their state +asynchronously. + +Static Lifecycle Methods +------------------------ + +### `getInitialAsyncState(params, query, setState)` + +Fetches state for a component after it mounts. Much like the familiar +`getInitialState` method, `getInitialAsyncState` should return a hash of +key/value pairs to use in the component's state. The difference is that +the values may be promises. As these values resolve, the component's +state is updated. + +#### Parameters + +##### params (object) + +The url parameters. + +##### query (object) + +The url query parameters + +##### setState (function) + +A function that can be used to `setState` as it is received, useful for +things like `xhr` progress and streamed data. Typically you won't use +this. + +Props +----- + +### `initialAsyncState` + +When testing, use the `initialAsyncState` prop to simulate asynchronous +data fetching. When this prop is present, no attempt is made to retrieve +additional state via `getInitialAsyncState`. + +Examples +-------- + +In it simplest form, just return a hash of promises, they become state: + +```js +var User = React.createClass({ + mixins: [ Router.AsyncState ], + + statics: { + getInitialAsyncState: function (params, query, setState) { + return { + user: fetchUser(params.userId), + activity: fetchActivityForUser(params.userId) + } + } + }, + + render: function() { + return this.state.user ? + <LoadingUserProfile/> : + <UserProfile user={this.state.user} activity={this.state.activity} />; + } +}); +``` + +But you can get fancier... + +```js +var User = React.createClass({ + mixins: [ Router.AsyncState ], + + statics: { + getInitialAsyncState: function (params, query, setState) { + var buffer = ''; + + return { + user: getUserByID(params.userID) // may be a promise + activity: {}, // an immediate value (not a promise) + stream: getStreamingData(params.userID, function (chunk) { + // `getStreamingData` returns a promise, but also calls back as + // data is received, giving us a chance to update the UI with + // progress using the `AsyncState` specific `setState` + // function + buffer += chunk; + setState({ streamBuffer: buffer }); + }) + }; + } + }, + + getInitialState: function () { + return { + user: null, // Receives a value when getUserByID resolves. + stream: null, // Receives a value when getStreamingData resolves. + streamBuffer: '' // Used to track data as it loads. + }; + }, + + render: function () { + if (!this.state.user) + return <LoadingUser/>; + + return ( + <div> + <p>Welcome {this.state.user.name}!</p> + <p>So far, you've received {this.state.streamBuffer.length} data!</p> + </div> + ); + } +}); +``` + diff --git a/web/src/vendor/react-router/docs/guides/overview.md b/web/src/vendor/react-router/docs/guides/overview.md new file mode 100644 index 00000000..9acd8115 --- /dev/null +++ b/web/src/vendor/react-router/docs/guides/overview.md @@ -0,0 +1,373 @@ +React Router Guide +================== + +Nesting UI is at the core of React Router. Think about any user +interface you're accustomed to, there is likely some shared UI as you +navigate around the application. + +Let's imagine a little app with a dashboard, inbox, and calendar. + +``` ++---------------------------------------------------------+ +| +---------+ +-------+ +--------+ | +| |Dashboard| | Inbox | |Calendar| Logged in as Joe | +| +---------+ +-------+ +--------+ | ++---------------------------------------------------------+ +| | +| Dashboard | +| | +| | +| +---------------------+ +----------------------+ | +| | | | | | +| | + + | +---------> | | +| | | | | | | | +| | | + | | +-------------> | | +| | | | + | | | | | +| | | | | | | | | | +| +-+---+----+-----+----+ +----------------------+ | +| | ++---------------------------------------------------------+ +``` + +We have three main screens here with the top section of UI being +persistent. + +Without React Router +-------------------- + +Without this router, you'd share that UI by repeating render code across +your views, probably with a `<Header/>` component: + +```js +var Header = React.createClass({ + render: function() { + return ( + <header> + <ul> + <li><a href="/">Dashboard</a></li> + <li><a href="/inbox">Inbox</a></li> + <li><a href="/calendar">Calendar</a></li> + </ul> + Logged in as Joe + </header> + ); + } +}); + +var DashboardRoute = React.createClass({ + render: function() { + return ( + <div> + <Header/> + <Dashboard/> + </div> + ); + } +}); + +var InboxRoute = React.createClass({ + render: function() { + return ( + <div> + <Header/> + <Inbox/> + </div> + ); + } +}); + +var CalendarRoute = React.createClass({ + render: function() { + return ( + <div> + <Header/> + <Calendar/> + </div> + ); + } +}); + +// Not React Router API +otherRouter.route('/', function() { + React.renderComponent(<DashboardRoute/>, document.body); +}); + +otherRouter.route('/inbox', function() { + React.renderComponent(<InboxRoute/>, document.body); +}); + +otherRouter.route('/calendar', function() { + React.renderComponent(<CalendarRoute/>, document.body); +}); + +``` + +The three main view's render methods are nearly identical. While one +level of shared UI like this is pretty easy to handle, getting deeper +and deeper adds more complexity, along with lots of `switch` branching, +etc. + +React Router embraces this common pattern among user interfaces by +nesting the views for you. + +With React Router +----------------- + +Here's how it works: + +1. You declare your view hierarchy with nested `<Route/>`s and provide + them with a React component to handle the route when its active. + +2. React Router will match the deepest route against the URL, and then + activate the entire tree of routes on that branch, nesting all the + UI. + +3. You access the active route handler in the props of the parent route. + +```js +var App = React.createClass({ + render: function() { + return ( + <div> + <header> + <ul> + <li><Link to="app">Dashboard</Link></li> + <li><Link to="inbox">Inbox</Link></li> + <li><Link to="calendar">Calendar</Link></li> + </ul> + Logged in as Joe + </header> + + {/* this is the important part */} + <this.props.activeRouteHandler/> + </div> + ); + } +}); + +var routes = ( + <Routes location="history"> + <Route name="app" path="/" handler={App}> + <Route name="inbox" handler={Inbox}/> + <Route name="calendar" handler={Calendar}/> + <DefaultRoute handler={Dashboard}/> + </Route> + </Routes> +); + +React.renderComponent(routes, document.body); +``` + +When the user lands at `/inbox`, the route named `inbox` gets matched so +its parent route will render the `App` component, and since `inbox` is +active, you get `Inbox` as `this.props.activeRouteHandler`. This is +nearly identical to `{{outlet}}` from Ember or `<div ng-view/>` from +angular. + +When the user navigates to `/calendar`, the same thing happens except +now `Calendar` is the `activeRouteHandler` in `App`'s render method. + +Finally, when the user navigates to the path `/`, `App` is active, and +notices that it has a `DefaultRoute`, so it receives `Dashboard` as the +`activeRouteHandler`. If a `DefaultRoute` is defined, it will be active +when the parent's route is matched exactly. + +Note that we don't need the `<Header/>` component since we don't have to +repeat it anymore. React Router shares that UI for us from one place. + +More Nesting +------------ + +Nesting arbitarily deep UI is not a problem. Consider the `Inbox` +screen: it has a master list of messages on the left, a detail view of +the message on the right, and a toolbar over the top. The toolbar and +list are persistent, meanwhile the message view changes as the user +navigates through the messages. + +``` ++---------------------------------------------------------------------+ +| +---------+ +-------+ +--------+ | +| |Dashboard| | Inbox | |Calendar| Logged in as Joe | +| +---------+ +-------+ +--------+ | ++---------------------------------------------------------------------+ +| +---------+ +-------+ +--------------+ | +| | Compose | | Reply | |Inbox Settings| | +| +---------+ +-------+ +--------------+ | ++-------------------+-------------------------------------------------+ +| David Brown | | +| Hey, we need to...| | +| | | +| 12:30pm | | ++-------------------+ 32 Unread Messages | +| Mary Sweeney | | +| I followed up w...| 456 Total Messages | +| | | +| 12:10pm | 3 Draft Messages | ++-------------------+ | +| DeMarcus Jones | | +| check this out ...| | +| | | +| 11:25am | | ++-------------------+-------------------------------------------------+ +``` + +Let's see how React Router handles this: + +```js +var Inbox = React.createClass({ + render: function() { + return ( + <div> + <Toolbar/> + <Messages/> + <this.props.activeRouteHandler/> + </div> + ); + } +}); + +var routes = ( + <Routes location="history"> + <Route handler={App}> + + <Route name="inbox" handler={Inbox}> + <Route name="message" path=":messageId" handler={Message}/> + <DefaultRoute handler={InboxStats}/> + </Route> + + <Route name="calendar" handler={Calendar}/> + <DefaultRoute handler={Dashboard}/> + + </Route> + </Routes> +); +``` + +- Inbox now has `this.props.activeRouteHandler` in its render method, + exactly like its parent. +- We added a child routes to `inbox`; messages or the stats page can now + render into it. + +Nesting a new level of UI does not increase the complexity of your code. +You simply nest some routes and render them with `activeRouteHandler`. + +Dynamic Segments +---------------- + +When we added the `message` route, we introduced a "dynamic segment" to +the URL. These segements get parsed from the url and passed into your +route handler on `this.props.params`. + +Remember our message route looks like this: + +```xml +<Route name="message" path=":messageId" handler={Message}/> +``` + +Lets look at accessing the `messageId` in `Message`. + +```js +var Message = React.createClass({ + render: function() { + return ( + <div>{this.props.params.messageId}</div> + ); + } +}); +``` + +Assuming the user navigates to `/inbox/123`, `this.props.params.messageId` is +going to be `'123'`. Check out the [AsyncState][AsyncState] mixin to see +how you can turn this parameter into state on your component. Or for a +more basic approach, make an ajax call in `componentDidMount` with the +value. + +Important Note About Dynamic Segments +------------------------------------- + +If you have dynamic segments in your URL, a transition from `/users/123` +to `/users/456` does not call `getInitialState`, `componentWillMount` or +`componentWillUnmount`. If you are using those lifecycle hooks to fetch +data and set state, you will also need to implement +`componentWillReceiveProps` on your handler, just like any other +component whose props are changing. This way you can leverage the +performance of the React DOM diff algorithm. Look at the `Contact` +handler in the `master-detail` example. + +If you'd rather be lazy, you can use the `addHandlerKey` option and set +it to `true` on your route to opt-out of the performance. See also +[Route][Route]. + +Scrolling +--------- + +By default, the router will manage the scroll position between route +transitions. When a user clicks "back" or "forward", it will restore +their scroll position. If they visit a new route, it will automatically +scroll the window to the top. You can opt out of this with the +`preserverScrollPosition` option on [Routes][Routes] or [Route][Route]. + +Bells and Whistles +------------------ + +### `<Link/>` + +The `<Link/>` component allows you to conveniently navigate users around +the application with accessible anchor tags that don't break normal link +functionality like control/command clicking to open in a new tab. Also, +when the route a link references is active, you get the `active` css +class to easily style your UI. + +### `<NotFoundRoute/>` + +At any level of your UI nesting, you can render a handler if the url +beyond what was matched isn't recognized. + +```xml +<Routes location="history"> + <Route path="/" handler={App}> + <Route name="inbox" path="/inbox" handler={Inbox}> + <!-- + will render inside the `Inbox` UI for any paths not recognized + after the parent route's path `/inbox/*` + --> + <NotFoundRoute handler={InboxNotFound} + <Route name="message" path="/inbox/:messageId" handler={Message}/> + <DefaultRoute handler={InboxStats}/> + </Route> + <Route name="calendar" path="/calendar" handler={Calendar}/> + <DefaultRoute handler={Dashboard}/> + </Route> + <!-- will catch any route that isn't recognized at all --> + <NotFoundRoute handler={NotFound} +</Routes> +``` + +### `<Redirect/>` + +URLs in an app change, so we made it easy to not break the old ones. + +```xml +<Route name="message" path="/inbox/:messageId" handler={Message} /> +<Redirect path="/messages/:messageId" to="message" /> +``` + +Path Matching +------------- + +There's a lot more to be said about path matching, check out the [Path +Matching Guide][path-matching]. + +API Documentation +----------------- + +That's the gist of what this router is all about, but there's a lot more +it has to offer. Check out the [API Docs][API] to learn about +redirecting transitions, query parameters and more. + + [AsyncState]:../api/mixins/AsyncState.md + [Route]:../api/components/Route.md + [Routes]:../api/components/Routes.md + [API]:../api/ + [path-matching]:./path-matching.md + diff --git a/web/src/vendor/react-router/docs/guides/path-matching.md b/web/src/vendor/react-router/docs/guides/path-matching.md new file mode 100644 index 00000000..67eadce9 --- /dev/null +++ b/web/src/vendor/react-router/docs/guides/path-matching.md @@ -0,0 +1,83 @@ +Path Matching +============= + +Relative v. Absolute Paths +-------------------------- + +Paths that start with `/` are absolute, paths that don't are relative, +meaning they extend their parent's path. + +```xml +<Route path="/"> + <!-- /courses/123 --> + <Route path="courses/:courseId"> + <!-- /courses/123/anouncements --> + <Route path="announcements" /> + <!-- /courses/123/dashboard --> + <Route path="dashboard" /> + </Route> + <!-- /inbox --> + <Route path="inbox"> + <!-- /messages/123 --> + <Route path="/messages/:messageId"/> + </Route> +</Route> +``` + +Absolute paths allow you to use any URL you want while maintaining the +automatic view nesting of the router. + +Dynamic Segments +---------------- + +Dynamic segements are defined with a `:`, like `:userId`. They will be +parsed and available by name in your route handler on +`this.props.params`. They match most characters except `. / ? #`. + +Splats +------ + +Splats are defined with `*` and will non-greedily match anything. The +value will be available in your route handler as +`this.props.params.splat`. If there are multiple, you'll get an array of +values. + +Question Mark +------------- + +Question marks will optionally match the preceeding segment. + +Examples +-------- + +``` +path: /file/:name.?:ext? +matches: + /file/foo.js + this.props.params: {name: 'foo', ext: 'js'} + /file/foo + this.props.params: {name: 'foo'} +does not match: + /file/foo.bar.js + /file/quux/baz.js + +path: /file/* +matches: + /file/foo.bar.js + this.props.params: {splat: 'foo.bar.js'} + /file/quux/baz.js + this.props.params: {splat: 'quux/baz.js'} + +path: /foo/*/:bar/?*? +matches: + /foo/a.b.c/taco/def + this.props.params: {bar: 'taco', splat: ['a.b.c', 'def']} + /foo/a.b.c/taco + this.props.params: {bar: 'taco', splat: 'a.b.c'} +does not match: + /foo/a.b.c + +path: * +matches everything, but you probably want `<NotFoundRoute/>` +``` + |