forked from reactjs/react-router-tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f9f476f
commit 50f7f54
Showing
17 changed files
with
1,251 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
bundle.js | ||
*.bundle.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
React Router Tutorial | ||
===================== | ||
|
||
Quick lessons for getting up-to-speed with React Router. | ||
|
||
See [01-setting-up.md](/lessons/01-setting-up.md) to get started. | ||
|
||
Each lesson has a commit for the final code so you can `git checkout | ||
<previous lesson final sha>` before starting a new one if you'd like. | ||
|
||
Missing stuff that will come eventually, hopefully ... maybe. | ||
|
||
1. an app that isn't completely pointless | ||
- egghead.io videos | ||
- code splitting | ||
- location state | ||
- data integration | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Setting up the Project | ||
|
||
First you'll need [Node.js](https://nodejs.org) and the package manager | ||
that comes with it: [npm](https://www.npmjs.com/). | ||
|
||
Once you've got that working, head to the command line where we'll set | ||
up our project. | ||
|
||
## Clone the Tutorial | ||
|
||
``` | ||
git clone <tutorial url> | ||
cd react-router-tutorial | ||
git checkout start | ||
npm start | ||
``` | ||
|
||
Now open up http://localhost:8080 | ||
|
||
Feel free to poke around the code to see how we're using webpack and npm | ||
scripts to run the app. | ||
|
||
You should see a "Hello React Router" message in the browser. | ||
|
||
## Make Some Changes | ||
|
||
Open up `modules/App.js` and change the text to something like "Hello | ||
<your name>". The browser automatically reloads with your new code. | ||
|
||
--- | ||
|
||
[Next: Rendering a Router](02-rendering-a-router.md) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Rendering a Router | ||
|
||
At its heart, React Router is a component. | ||
|
||
```js | ||
render(<Router/>, document.getElementById('app')) | ||
``` | ||
|
||
That's not going display anything until we configure a route. | ||
|
||
Open up `index.js` and | ||
|
||
1. import `Router` and `Route` | ||
2. render a `Router` instead of `App` | ||
|
||
```js | ||
// ... | ||
import { Router, Route, hashHistory } from 'react-router' | ||
|
||
render(( | ||
<Router history={hashHistory}> | ||
<Route path="/" component={App}/> | ||
</Router> | ||
), document.getElementById('app')) | ||
``` | ||
|
||
Make sure your server is running with `npm start` and then visit | ||
http://localhost:8080 | ||
|
||
You should get the same screen as before, but this time with some junk | ||
in the URL. We're using `hashHistory`--it manages the routing history | ||
with the hash portion of the url. It's got that extra junk to shim some | ||
behavior the browser has natively when using real urls. We'll change | ||
this to use real urls later and lose the junk, but for now, this works | ||
great because it doesn't require any server-side configuration. | ||
|
||
## Adding More Screens | ||
|
||
Create two new components at: | ||
|
||
- `modules/About.js` | ||
- `modules/Repos.js` | ||
|
||
```js | ||
// modules/About.js | ||
import React from 'react' | ||
|
||
export default React.createClass({ | ||
render() { | ||
return <div>About</div> | ||
} | ||
}) | ||
``` | ||
|
||
```js | ||
// modules/Repos.js | ||
import React from 'react' | ||
|
||
export default React.createClass({ | ||
render() { | ||
return <div>Repos</div> | ||
} | ||
}) | ||
``` | ||
|
||
Now we can couple them to the app at their respective paths. | ||
|
||
```js | ||
import About from './modules/About' | ||
import Repos from './modules/Repos' | ||
|
||
render(( | ||
<Router history={hashHistory}> | ||
<Route path="/" component={App}/> | ||
{/* add the routes here */} | ||
<Route path="/repos" component={Repos}/> | ||
<Route path="/about" component={About}/> | ||
</Router> | ||
), document.getElementById('app')) | ||
``` | ||
|
||
Now visit http://localhost:8080/#/about and | ||
http://localhost:8080/#/repos | ||
|
||
--- | ||
|
||
[Next: Navigating With Link](03-navigating-with-link.md) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Navigating with Link | ||
|
||
Perhaps the most used component in your app is `Link`. Its almost | ||
identical to the `<a/>` tag you're used to except that its aware of | ||
the `Router` it was rendered in. | ||
|
||
Lets create some navigation in our `App` component. | ||
|
||
```js | ||
// modules/App.js | ||
import { Link } from 'react-router' | ||
|
||
export default React.createClass({ | ||
render() { | ||
return ( | ||
<div> | ||
<h1>React Router Tutorial</h1> | ||
<ul role="nav"> | ||
<li><Link to="/about">About</Link></li> | ||
<li><Link to="/repos">Repos</Link></li> | ||
</ul> | ||
</div> | ||
) | ||
} | ||
}) | ||
``` | ||
|
||
Now visit http://localhost:8080/ and click the links, click back, click | ||
forward. It works! | ||
|
||
--- | ||
|
||
[Next: Nested Routes](04-nested-routes.md) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# Nested Routes | ||
|
||
The navigation we added to `App` should probably be present on every | ||
screen. Without React Router, we could wrap that `ul` into a | ||
component, say `Nav`, and render a `Nav` on every one of our screens. | ||
|
||
This approach isn't as clean as the application grows. React Router | ||
provides another way to share UI like this with nested routes, a trick | ||
it learned from [Ember](http://emberjs.com) (/me tips hat). | ||
|
||
## Nested UI and Nested URLs | ||
|
||
Have you ever noticed your app is just a series of boxes inside boxes | ||
inside boxes? Have you also noticed your URLs tend to be coupled to that | ||
nesting? For example given this url, `/repos/123`, our | ||
components would probably look like this: | ||
|
||
```js | ||
<App> {/* / */} | ||
<Repos> {/* /repos */} | ||
<Repo/> {/* /repos/123 */} | ||
</Repos> | ||
</App> | ||
``` | ||
|
||
And our UI something like: | ||
|
||
``` | ||
+-------------------------------------+ | ||
| Home Repos About | <- App | ||
+------+------------------------------+ | ||
| | | | ||
Repos -> | repo | Repo 1 | | ||
| | | | ||
| repo | Boxes inside boxes | | ||
| | inside boxes ... | <- Repo | ||
| repo | | | ||
| | | | ||
| repo | | | ||
| | | | ||
+------+------------------------------+ | ||
``` | ||
|
||
React Router embraces this by letting you nest your routes, which | ||
automatically becomes nested UI. | ||
|
||
## Sharing Our Navigation | ||
|
||
Lets nest our `About` and `Repos` components inside of `App` so that we | ||
can share the navigation with all screens in the app. We do it in two | ||
steps: | ||
|
||
First, let the `App` `Route` have children, and move the other routes | ||
underneath it. | ||
|
||
```js | ||
// index.js | ||
// ... | ||
render(( | ||
<Router history={hashHistory}> | ||
<Route path="/" component={App}> | ||
{/* make them children of `App` */} | ||
<Route path="/repos" component={Repos}/> | ||
<Route path="/about" component={About}/> | ||
</Route> | ||
</Router> | ||
), document.getElementById('app')) | ||
``` | ||
|
||
Next, render children inside of `App`. | ||
|
||
```js | ||
// modules/App.js | ||
// ... | ||
render() { | ||
return ( | ||
<div> | ||
<h1>Ghettohub Issues</h1> | ||
<ul role="nav"> | ||
<li><Link to="/about">About</Link></li> | ||
<li><Link to="/repos">Repos</Link></li> | ||
</ul> | ||
|
||
{/* add this */} | ||
{this.props.children} | ||
|
||
</div> | ||
) | ||
} | ||
// ... | ||
``` | ||
|
||
Alright, now go click the links and notice that the `App` component | ||
continues to render while the child route's component gets swapped | ||
around as `this.props.children` :) | ||
|
||
React Router is constructing your UI like this: | ||
|
||
```js | ||
// at /about | ||
<App> | ||
<About/> | ||
</App> | ||
|
||
// at /repos | ||
<App> | ||
<Repos/> | ||
</App> | ||
``` | ||
|
||
## By Small and Simple Things are Great Things Brought to Pass | ||
|
||
The best way to build large things is to stitch small things together. | ||
|
||
This is the real power of React Router, every route can be developed | ||
(even rendered!) as an independent application. Your route configuration | ||
stitches all these apps together however you'd like. Applications | ||
inside of Applications, boxes inside of boxes. | ||
|
||
What happens if you move the `About` route outside of `App`? | ||
|
||
Okay, now put it back. | ||
|
||
--- | ||
|
||
[Next: Active Links](05-active-links.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Active Links | ||
|
||
One way that `Link` is different from `a` is that it knows if the path | ||
it links to is active so you can style it differently. | ||
|
||
## Active Styles | ||
|
||
Let's see how it looks with inline styles, add `activeStyle` to your | ||
`Links`s. | ||
|
||
```js | ||
// modules/App.js | ||
<li><Link to="/about" activeStyle={{ color: 'red' }}>About</Link></li> | ||
<li><Link to="/repos" activeStyle={{ color: 'red' }}>Repos</Link></li> | ||
``` | ||
|
||
How as you navigate, the active link is red. | ||
|
||
## Active Class Name | ||
|
||
You can also use an active class name instead of inline-styles. | ||
|
||
```js | ||
<li><Link to="/about" activeClassName="active">About</Link></li> | ||
<li><Link to="/repos" activeClassName="active">Repos</Link></li> | ||
``` | ||
|
||
We don't have a stylesheet on the page yet though. Lets add one--extra | ||
points if you can add a `link` tag from memory. Double extra points if | ||
you can leave the attributes unquoted, against your better judgement. | ||
|
||
```html | ||
<link rel=stylesheet href=index.css /> | ||
``` | ||
|
||
And the css file: | ||
|
||
```css | ||
.active { | ||
color: green; | ||
} | ||
``` | ||
|
||
You'll need to manually refresh the browser since Webpack isn't building | ||
our `index.html`. | ||
|
||
## Nav Link Wrappers | ||
|
||
Most links in your site don't need to know they are active, usually just | ||
primary navigation links need to know. Its useful to wrap those so you | ||
don't have to remember what your `activeClassName` or `activeStyle` is | ||
everywhere. | ||
|
||
Create a new file at `modules/NavLink.js` that looks like this: | ||
|
||
```js | ||
// modules/NavLink.js | ||
import React from 'react' | ||
import { Link } from 'react-router' | ||
|
||
export default React.createClass({ | ||
render() { | ||
return <Link {...this.props} activeClassName="active"/> | ||
} | ||
}) | ||
``` | ||
|
||
Now you can go change your links to `NavLink`s. | ||
|
||
```js | ||
// App.js | ||
import NavLink from './NavLink' | ||
|
||
// ... | ||
|
||
<li><NavLink to="/about">About</NavLink></li> | ||
<li><NavLink to="/repos">Repos</NavLink></li> | ||
``` | ||
|
||
Oh, how beautiful upon the renders is the composability of components. | ||
|
||
--- | ||
|
||
[Next: Params](06-params.md) | ||
|
Oops, something went wrong.