React Route

有幸你能看来我的这篇文章,这篇文章是继React后面写的Reactroute,所以你需要看看我前面整理的React笔记再来看Reactroute可能更容易

All the work we’ve done so far has either been in index.js or Detail.js, but now we’re going to add a third file called List.js that will render a home page for our app. From there, users will be able to select a GitHub repository, and doing so will show Detail.js as before.

So, we’ll go from having just one page listing all the React commits, forks and pulls on GitHub, to having a homepage first where users can select React, React Native, Jest, or other Facebook projects of our choosing. This involves a fairly big change, so we’re going to do this in two parts: first implement React Router in a way that preserves the exact behavior we have right now, then second add the new home page.

If you were wondering, React Router is a component that loads different pages depending on the URL your user asked for. So if the user goes tohttp://localhost:8080/helloit would serve one page, and http://localhost:8080/world would serve a different page.

Well, that’s not strictly true. To avoid having to add a server configuration, the pages React Router serves up will all start with/#/, e.g. http://localhost:8080/#/hello. This means thatindex.htmlwill automaticallybeusedtorenderallpages,whichinturnmeansthatReactRouterwillbeabletoload the right page.

src/index.js

 1   import React from 'react';
 2   import ReactDOM from 'react-dom';
 3   import { Router, Route, IndexRoute } from 'react-router';
 4   import createHistory from 'histroy/lib/createHistory';
 5  
 6  import Detail from '.page/Detail';
 7   
 8   ReactDOM.render(                                         
 9      <Router>                       //<Router history={creatHistory({ queryKey: false})}
10          <Route path="/" compent={ Detail } />     // onUpdate={() => window.sorollTo(0,0)}>//is right
11      </Router>,
12     document.getElementById('app')
13  );//is wrong

/剖析Router,Route The first import brings three components, of which we’ll be using two immediately and the other shortly. Router is React Router itself, which takes a listofURLs and React components and puts the two together. Route is one individual URL mapping, e.g. the URL detail and our Detail component. IndexRoute is used as a default route; we’ll get onto that soon.

How to Add a New Route to React Router

src/index.js

 1 import React from 'react';
 2 import ReactDOM from 'react-dom';
 3 import { Router, Route, IndexRoute } from 'react-router';
 4 import createHistory from 'histroy/lib/createHistory';
 5 
 6 import Detail from '.page/Detail';
 7 import List from './pages/List';
 8 
 9 ReactDOM.render(
10     <Router history = { createHistory({ queryKey: false })}
11         onUpdate = {() => window.scrollTo(0, 0)}>
12         <Route path = "/" compent = {List} />
13         <Route path="/react" compent={ Detail } />
14     </Router>,
15     document.getElementById('app')
16 );

Creating a Link Between Pages in React Router

src/pages/List

 1 import React from 'react';
 2 import ReactDOM from 'react-dom';
 3 import { Router, Route, IndexRoute } from 'react-router';
 4 import createHistory from 'histroy/lib/createHistory';
 5 import { Link } from 'react-router'
 6 
 7 import Detail from '.page/Detail';
 8 import List from './pages/List';
 9 
10 class List extends React.Compent {
11      render() (
12          <div>
13              <p>Please choose a repository from the list below.</p>
14              <ul>
15 <li><link to = "/detail/react"> React</Link></li> 16 18 </ul> 19 </div> 20 ); 21 }
export default List;

Making Custom URLs with React Router Params

使用React Router里自定义的URLs参数

We currently have these two routes defined in index.js:

 1 <Route path = "/" compent = {List} /> 2 <Route pate = "/react" compent = { Detail } />
     

now

src/index.js

1 <Route path="/" component={ List } /> 
2 <Route path="/detail/:repo" component={ Detail } />
//代替了
<Route path="/" component={ List } />
<Route path="/react" component={ Detail } />
<Route path="/react-native" component={ Detail } />
<Route path="/jest" component={ Detail } />

:repo in the URL, React Router will automatically pull out whatever text comes in that part of the URL, then pass it to the Detail component to acton. Sure, we still need to actually do something with the repository name, but it means the Detail component will now work for /detail/react, /detail/react-native and so on.

src/pages/Detail.js

1 ajax.get(`https://api.github.com/repos/facebook/react/${type}`)
//上面的代码由下面的代码取代
1const baseURL = 'https://api.github.com/repos/facebook';
2 ajax.get(`${baseURL}/${this.props.params.repo}/${type}`)

Ifyouremember,thatusesES6stringinterpolationsothattheURLgetswrittenas…/react/commits, …/react/pulls, etc. Thanks to the magic of React Router, we can use the exact same technique with thenameoftherepositorytoo.Weused:repo inside our route, and React Router will automatically make that available to the Detail component as this.props.params.repo.

src/pages/List.js

 1 import React from 'react';
 2 import ReactDOM from 'react-dom';
 3 import { Router, Route, IndexRoute } from 'react-router';
 4 import createHistory from 'histroy/lib/createHistory';
 5 import { Link } from 'react-router'
 6 
 7 import Detail from '.page/Detail';
 8 import List from './pages/List';
 9 
10 class List extends React.Compent {
11      render() (
12          <div>
13              <p>Please choose a repository from the list below.</p>
14              <ul>
15                  <li><link to = "/detail/react"> React</Link></li>
16                  <li><link to = "/detail/react-native"> React-Native</Link></li>
17                  <li><Link to = "/detail/jest">Jest</Link></li>
18              </ul>
19          </div>
20      );
21 }

Adding a Root Route Using React Router and Index Route

Let’s get started now: create a new file in the src/pages directory, and call it App.js. We’ll use this to show some basic branding for our web app, then show all the content from our child page below. Please give the new file this content:

src/pages/App.js

 1 import React from 'react';
 2 
 3 class App extends React.Compent {
 4     render() {
 5         return (
 6         <div>
 7             <h1>Unofficial GitHub Browser v0.1</h1>
 8             { this.props.children}
 9         </div>
10         );
11     }
12 }
13 
14 export default App;

The only really interesting part of that code is {this.props.children}. All it means is “render my child components here,” so all this new App component does is add a heading above whatever page component is rendered beneath it – i.e., our List and Detail components.

The page itself was simple enough, but now we need to update our index.js file, and this is a little trickier because you need to learn two new concepts:

• Any route can have child routes inside it, and these build upon the parent route.

• If you want a child route to be used as the default when no other child matches, you use a special route called <IndexRoute>.

 1 import React from 'react';
 2 import ReactDOM from 'react-dom';
 3 import {Router, Route, IndexRoute } from 'react-router';
 4 import createHistory from 'history/lib/createHashHistory';
 5 
 6 import App from './pages/App';
 7 import List from './pages/List';
 8 import Detail from './pages/Detail';
 9 
10 ReactDOM.render(
11     <Router history = {createHistory({ queryKey: false })}
12         onUpdate = {() => window.scrollTo(0,0)}>
13         <Route path = "/" compent = { App }>
14             <IndexRoute compent = { List } />
15             <Route path = "detail/:repo" compent = { Detail } />
16         </Route>
17     </Router>,
18     document.getElementById('app')
19 );

That’s the React Router structure for those two new concepts I just introduced. First, notice the new <IndexRoute> component: it means “if my parent route was matched but none of my siblings matched, render me.” Second, notice how <Route path="/" component={ App }> actually contains two things inside it: the IndexRoute and another Route.

The <IndexRoute> is important, and to explain what it does let’s pretend it isn’t there. If the user navigatestohttp://localhost:8080/,itwouldmatchtheApproute(path=”/”),butitwouldn’tmatch the Detail route (path=”detail/:repo”), so all they would see is “Unofficial GitHub Browser v0.1” in large text.

Cleaning up Our Routes and Preparing for the Next Step

src/routes.js

 1 import React from 'react';
 2 import { Route, IndexRoute } from 'react-router';
 3 
 4 
 5 import App from './pages/App';
 6 import List from './pages/List';
 7 import Detail from './pages/Detail';
 8 
 9 const routes = (
10         <Route path = "/" compent = { App }>
11             <IndexRoute compent = { List } />
12             <Route path = "detail/:repo" compent = { Detail } />
13         </Route>
14 );
15 
16 export default routes;
 src/index.js
1import React from 'react'; 2 import ReactDOM from 'react-dom'; 3 import { Router} from 'react-router'; 4 import createHistory from 'history/lib/createHashHistory'; 5 6 import routes from './routes'; 7 8 ReactDOM.render( 9 <Router history = {createHistory({ queryKey: false })} 10 onUpdate = {() => window.scrollTo(0,0)}> 11 {routes} 12 </Router>, 13 document.getElementById('app') 14 );