to work.
## React Router Examples
1. clone [React-Router](https://github.com/rackt/react-router.git)
2. run npm install
3. npm start
4. http://localhost:8080
abundance case
* active-links
```
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Index}/>
<Route path="/about" component={About}/>
<Route path="users" component={Users}>
<IndexRoute component={UsersIndex}/>
<Route path=":id" component={User}/>
</Route>
</Route>
</Router>
), document.getElementById('example'))
* animations
```
<ReactCSSTransitionGroup
component="div"
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
{React.cloneElement(this.props.children, {
key: this.props.location.pathname
})}
</ReactCSSTransitionGroup>
* auth-flow
```
module.exports = {
login(email, pass, cb) {
cb = arguments[arguments.length - 1]
if (localStorage.token) {
if (cb) cb(true)
this.onChange(true)
return
}
pretendRequest(email, pass, (res) => {
if (res.authenticated) {
localStorage.token = res.token
if (cb) cb(true)
this.onChange(true)
} else {
if (cb) cb(false)
this.onChange(false)
}
})
},
getToken() {
return localStorage.token
},
logout(cb) {
delete localStorage.token
if (cb) cb()
this.onChange(false)
},
loggedIn() {
return !!localStorage.token
},
onChange() {}
}
function pretendRequest(email, pass, cb) {
setTimeout(() => {
if (email === 'joe@example.com' && pass === 'password1') {
cb({
authenticated: true,
token: Math.random().toString(36).substring(7)
})
} else {
cb({ authenticated: false })
}
}, 0)
}
* auth-with-shared-root
route config
* dynamic-segments
```
class Task extends React.Component {
render() {
const { userID, taskID } = this.props.params
return (
User ID: {userID}
Task ID: {taskID}
)
}
}
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="user/:userID" component={User}>
<Route path="tasks/:taskID" component={Task} />
</Route>
</Route>
</Router>
), document.getElementById('example'))
* master-detail
ContactStore
* nested-animations
```
<ReactCSSTransitionGroup
component="div" transitionName="swap"
transitionEnterTimeout={500} transitionLeaveTimeout={500}
>
{React.cloneElement(this.props.children || , { key: key })}
</ReactCSSTransitionGroup>
* passing-props-to-children
```
{this.props.children && React.cloneElement(this.props.children, {
onRemoveTaco: this.handleRemoveTaco
})}
* huge-apps
global.COURSES=[];
import courses from '';
const rootRoute = {
component: 'div',
childRoutes: [ {
path: '/',
component: require('./components/App'),
childRoutes: [
require('./routes/Calendar'),
require('./routes/Course'),
require('./routes/Grades'),
require('./routes/Messages'),
require('./routes/Profile')
]
} ]
}
```
import React from 'react'
import { Link } from 'react-router'
const dark = 'hsl(200, 20%, 20%)'
const light = '#fff'
const styles = {}
styles.wrapper = {
padding: '10px 20px',
overflow: 'hidden',
background: dark,
color: light
}
styles.link = {
padding: 11,
color: light,
fontWeight: 200
}
styles.activeLink = {
...styles.link,
background: light,
color: dark
}
class GlobalNav extends React.Component {
constructor(props, context) {
super(props, context)
this.logOut = this.logOut.bind(this)
}
logOut() {
alert('log out')
}
render() {
const { user } = this.props
return (
<div style={styles.wrapper}>
<div style=>
<Link to="/" style={styles.link}>Home</Link>{' '}
<Link to="/calendar" style={styles.link} activeStyle={styles.activeLink}>Calendar</Link>{' '}
<Link to="/grades" style={styles.link} activeStyle={styles.activeLink}>Grades</Link>{' '}
<Link to="/messages" style={styles.link} activeStyle={styles.activeLink}>Messages</Link>{' '}
<div style=>
<Link style={styles.link} to="/profile">{user.name}</Link> <button onClick={this.logOut}>log out</button>
</div>
</div>
)
}
}
GlobalNav.defaultProps = {
user: {
id: 1,
name: 'Ryan Florence'
}
}
export default GlobalNav
transform var to subclass
```
class App extends React.Component {
render() {
return (
<div style=>
{this.props.children || <Dashboard courses={COURSES} />}
</div>
)
}
}
class Dashboard extends React.Component {
render() {
const { courses } = this.props
return (
Super Scalable Apps
Open the network tab as you navigate. Notice that only the amount of
your app that is required is actually downloaded as you navigate
around. Even the route configuration objects are loaded on the fly.
This way, a new route added deep in your app will not affect the
initial bundle of your application.
Courses
{' '}
{courses.map(course => (
<li key={course.id}>
<Link to={`/course/${course.id}`}>{course.name}</Link>
</li>
))}
)
}
}
export default Dashboard
动态控制展示
{content}
```
const styles = {}
styles.sidebar = {
float: 'left',
width: 200,
padding: 20,
borderRight: '1px solid #aaa',
marginRight: 20
}
class Course extends React.Component {
render() {
let { sidebar, main, children, params } = this.props
let course = COURSES[params.courseId]
let content
if (sidebar && main) {
content = (
<div className="Sidebar" style={styles.sidebar}>
{sidebar}
<div className="Main" style=>
{main}
</div>
</div>
)
} else if (children) {
content = children
} else {
content =
}
return (
{course.name}
<Nav course={course} />
{content}
)
}
}
module.exports = Course
* pinterest
Modal return
```
{isModal && (
<Modal isOpen={true} returnTo={location.state.returnTo}>
{this.props.children}
</Modal>
)}
const Modal = React.createClass({
styles: {
position: 'fixed',
top: '20%',
right: '20%',
bottom: '20%',
left: '20%',
padding: 20,
boxShadow: '0px 0px 150px 130px rgba(0, 0, 0, 0.5)',
overflow: 'auto',
background: '#fff'
},
render() {
return (
<div style={this.styles}>
<Link to={this.props.returnTo}>Back</Link>
{this.props.children}
</div>
)
}
})
* query-params
```
class User extends React.Component {
render() {
let { userID } = this.props.params
let { query } = this.props.location
let age = query && query.showAge ? '33' : ''
return (
User id: {userID}
{age}
)
}
}
this.props.location have below attributes
type Location = {
pathname: Pathname;
search: QueryString;
query: Query;
state: LocationState;
action: Action;
key: LocationKey;
};
* ReouteComponent
In addition to children, route components receive the following props:
router – The router instance
location – The current location
params – The current params
route – The route that declared this component
routeParams – A subset of the params that were specified in the route's path
* sidebar
one sidebar data structure
```
onst data = [
{
name: 'Tacos',
description: 'A taco (/ˈtækoʊ/ or /ˈtɑːkoʊ/) is a traditional Mexican dish composed of a corn or wheat tortilla folded or rolled around a filling. A taco can be made with a variety of fillings, including beef, pork, chicken, seafood, vegetables and cheese, allowing for great versatility and variety. A taco is generally eaten without utensils and is often accompanied by garnishes such as salsa, avocado or guacamole, cilantro (coriander), tomatoes, minced meat, onions and lettuce.',
items: [
{ name: 'Carne Asada', price: 7 },
{ name: 'Pollo', price: 6 },
{ name: 'Carnitas', price: 6 }
]
},
{
name: 'Burgers',
description: 'A hamburger (also called a beef burger, hamburger sandwich, burger or hamburg) is a sandwich consisting of one or more cooked patties of ground meat, usually beef, placed inside a sliced bun. Hamburgers are often served with lettuce, bacon, tomato, onion, pickles, cheese and condiments such as mustard, mayonnaise, ketchup, relish, and green chile.',
items: [
{ name: 'Buffalo Bleu', price: 8 },
{ name: 'Bacon', price: 8 },
{ name: 'Mushroom and Swiss', price: 6 }
]
},
{
name: 'Drinks',
description: 'Drinks, or beverages, are liquids intended for human consumption. In addition to basic needs, beverages form part of the culture of human society. Although all beverages, including juice, soft drinks, and carbonated drinks, have some form of water in them, water itself is often not classified as a beverage, and the word beverage has been recurrently defined as not referring to water.',
items: [
{ name: 'Lemonade', price: 3 },
{ name: 'Root Beer', price: 4 },
{ name: 'Iron Port', price: 5 }
]
}
]
const dataMap = data.reduce(function (map, category) {
category.itemsMap = category.items.reduce(function (itemsMap, item) {
itemsMap[item.name] = item
return itemsMap
}, {})
map[category.name] = category
return map
}, {})
exports.getAll = function () {
return data
}
exports.lookupCategory = function (name) {
return dataMap[name]
}
exports.lookupItem = function (category, item) {
return dataMap[category].itemsMap[item]
}
## React Router Testing With Jest
[Jest](https://github.com/reactjs/react-router/blob/master/docs/guides/testing.md)