From 0510c9b111aed03d0d3680db63614d50f231745c Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 10 Sep 2014 14:22:26 +1200 Subject: Client-side framework for web application --- .../vendor/react-router/docs/guides/overview.md | 373 +++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 web/src/vendor/react-router/docs/guides/overview.md (limited to 'web/src/vendor/react-router/docs/guides/overview.md') 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 `
` component: + +```js +var Header = React.createClass({ + render: function() { + return ( +
+ + Logged in as Joe +
+ ); + } +}); + +var DashboardRoute = React.createClass({ + render: function() { + return ( +
+
+ +
+ ); + } +}); + +var InboxRoute = React.createClass({ + render: function() { + return ( +
+
+ +
+ ); + } +}); + +var CalendarRoute = React.createClass({ + render: function() { + return ( +
+
+ +
+ ); + } +}); + +// Not React Router API +otherRouter.route('/', function() { + React.renderComponent(, document.body); +}); + +otherRouter.route('/inbox', function() { + React.renderComponent(, document.body); +}); + +otherRouter.route('/calendar', function() { + React.renderComponent(, 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 ``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 ( +
+
+
    +
  • Dashboard
  • +
  • Inbox
  • +
  • Calendar
  • +
+ Logged in as Joe +
+ + {/* this is the important part */} + +
+ ); + } +}); + +var 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 `
` 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 `
` 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 ( +
+ + + +
+ ); + } +}); + +var 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 + +``` + +Lets look at accessing the `messageId` in `Message`. + +```js +var Message = React.createClass({ + render: function() { + return ( +
{this.props.params.messageId}
+ ); + } +}); +``` + +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 +------------------ + +### `` + +The `` 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. + +### `` + +At any level of your UI nesting, you can render a handler if the url +beyond what was matched isn't recognized. + +```xml + + + + + + + + + + + + +``` + +### `` + +URLs in an app change, so we made it easy to not break the old ones. + +```xml + + +``` + +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 + -- cgit v1.2.3