Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to React Router

Introduction to React Router

Learn to use React Router, a popular library in the React community, to manage navigation and rendering of components in React applications.

We’ll start with routing basics, then dive into React Router’s powerful features, including:

* Navigating routes
* Constructing a layout via nested routes
* Rendering index routes and links
* Styling active links
* Creating routes with parameters
* Displaying 404 routes and clean URLs
* What's new in React Router 4.

Guil Hernandez

November 22, 2016
Tweet

More Decks by Guil Hernandez

Other Decks in Programming

Transcript

  1. Routing Matches a URL to what’s being rendered in the

    browser — it does something in response to a change in the current URL
  2. Routing in React Mounts and unmounts components while matching the

    URL with the set of components being rendered
  3. Routing Should: • Keep track of browser history • Seamlessly

    link users to specific sections of your app • Be consistent with the navigation experience of regular multi- page sites and apps
  4. Custom router class App extends Component { state = {

    route: window.location.hash }; componentDidMount() { window.addEventListener('hashchange', () => { this.setState({ route: window.location.hash.substr(1) }); }); } … } // App.js
  5. Custom router class App extends Component { … render() {

    let Child; switch (this.state.route) { case '/about': Child = About; break; case '/work' : Child = Work; break; default : Child = Home; } return ( <div> <a href="#/">Home</a> <a href="#/about">About</a> <a href="#/work">Work</a> <Child /> </div> ); } … // App.js
  6. Routing As your app grows and you add more routes,

    your routing code will also grow in complexity

  7. Example hierarchy <App> <Home/> <Plans> <Silver/> <Gold/> </Plans> <SignUp/> </App>

    <Home/> <Courses> </Courses> <Teachers/> <HTML/> <CSS/> <JS/>
  8. React Router • A set of components • You write

    routes using JSX • Easier to visualize how your routes are structured
  9. Three main components import { Router, Route, Link } from

    'react-router'; , Route, Link Router
  10. Router import React from 'react'; import { Router } from

    'react-router'; import Home from './components/Home'; ReactDOM.render(( <Router> </Router> ), document.getElementById('root')); // index.js
  11. Declaring a route import React from 'react'; import { Router,

    Route } from 'react-router'; import Home from './components/Home'; ReactDOM.render(( <Router> <Route path="" component={} /> </Router> ), document.getElementById('root')); // index.js <Route path="" component={} />
  12. Declaring a route import React from 'react'; import { Router,

    Route } from 'react-router'; import Home from './components/Home'; ReactDOM.render(( <Router> <Route path="" component={} /> </Router> ), document.getElementById('root')); // index.js <Route path="/" component={Home} />
  13. Declaring multiple routes … import Home from './components/Home'; import Courses

    from './components/Courses'; import Teachers from './components/Teachers'; ReactDOM.render(( <Router> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} /> </Router> ), document.getElementById('root')); // index.js
  14. Declaring multiple routes … import Home from './components/Home'; import Courses

    from './components/Courses'; import Teachers from './components/Teachers'; ReactDOM.render(( <Router> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} /> </Router> ), document.getElementById('root')); // index.js
  15. History • Listens for changes in the URL • Provides

    information about which components to render • Lets users navigate using back and forward buttons • Keeps the UI in sync with the URL
  16. browserHistory import React from 'react'; import { Router, Route, browserHistory

    } from 'react-router'; … ReactDOM.render(( <Router history={browserHistory}> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} /> </Router> ), document.getElementById('root')); // index.js <Router history={browserHistory}> , browserHistory <Router>
  17. Navigate with Link class App extends Component { render() {

    return ( <div> <header> <ul className="main-nav"> <li><Link to="/">Home</Link></li> <li><Link to="/teachers">Teachers</Link></li> <li><Link to="/courses">Courses</Link></li> </ul> </header> … </div> ); } } // App.js … import { Link } from 'react-router';
  18. Active link styles class App extends Component { render() {

    return ( <div> <header> <ul className="main-nav"> <li><Link to="/" activeStyle={{ color: 'blue' }}>Home</Link></li> <li><Link to="/teachers" activeStyle={{ color: 'blue' }}>Teachers</Link></li> <li><Link to="/courses" activeStyle={{ color: 'blue' }}>Courses</Link></li> </ul> </header> … </div> ); } } // App.js … import { Link } from 'react-router';
  19. Active link styles class App extends Component { render() {

    return ( <div> <header> <ul className="main-nav"> <li><Link to="/" activeClassName="active">Home</Link></li> <li><Link to="/teachers" activeClassName="active">Teachers</Link></li> <li><Link to="/courses" activeClassName="active">Courses</Link></li> </ul> </header> … </div> ); } } // App.js … import { Link } from 'react-router';
  20. Wrapper component import React from 'react'; import { Link }

    from 'react-router'; const NavLink = props => ( <Link {...props} activeClassName="active" /> ); export default NavLink; // NavLink.js
  21. Wrapper component class App extends Component { render() { return

    ( <div> <header> <ul className="main-nav"> <li><NavLink to="/">Home</NavLink></li> <li><NavLink to="/teachers">Teachers</NavLink></li> <li><NavLink to="/courses">Courses</NavLink></li> </ul> </header> … </div> ); } } // App.js import NavLink from './NavLink';
  22. Component hierarchy <App> <Home/> <Plans> <Silver/> <Gold/> </Plans> <SignUp/> </App>

    <Home/> <Courses> </Courses> <Teachers/> <HTML/> <CSS/> <JS/>
  23. Nesting // index.js ReactDOM.render(( <Router history={browserHistory}> <Route component={App}> <Route path="/"

    component={Home} /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} /> </Route> </Router> ), document.getElementById('root')); <Route component={App}> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} /> </Route> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} />
  24. Nesting // App.js class App extends Component { render() {

    return ( <div> <ul className="main-nav"> <li><NavLink to="/">Home</NavLink></li> <li><NavLink to="/teachers">Teachers</NavLink></li> <li><NavLink to="/courses">Courses</NavLink></li> </ul> s.props.children } </div> ); } } { this.props.children }
  25. Nested routes URL Component / App -> Home /teachers App

    -> Teachers /courses App -> Courses
  26. Nesting deeper // index.js ReactDOM.render(( <Router history={browserHistory}> <Route component={App}> <Route

    path="/" component={Home} /> <Route path="/courses" component={Courses} /> Route path="/teachers" component={Teachers} /> < /Route> </Router> ), document.getElementById('root')); <Route component={App}> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <R oute path ="/teachers" component={Teachers} /> </Route> <Route path="/" component={Home} /> <Route path="/courses" component={Courses}> <Route path="/html" component={HTML} /> <Route path="/css" component={CSS} /> <Route path="/javascript" component={JS} /> </Route> <Route path="/teachers" component={Teachers} /> <Route path="html" component={HTML} /> <Route path="css" component={CSS} /> <Route path="javascript" component={JS} />
  27. Nesting deeper URL Component /courses/html App -> Courses -> HTML

    /courses/css App -> Courses -> CSS /courses/javascript App -> Courses -> JS
  28. When you pass props to <Route>, props can be used

    in the component rendered by that route.
  29. Passing props … ReactDOM.render(( <Router history={browserHistory}> <Route path="/" component={Home} title="Welcome

    Home!" /> <Route path="/courses" component={Courses} /> <Route path="/teachers" component={Teachers} /> </Router> ), document.getElementById('root')); // index.js
  30. Accessing route props // Home.js class Home extends Component {

    render() { return ( <div> <h1>{ this.props.route.title }</h1> … s.pr </div> ); } } .title
  31. Passing data as props ReactDOM.render(( <Router history={browserHistory}> <Route component={App}> <Route

    path="/" component={Home} /> <Route path="/courses" component={Courses} /> Route path="/teachers" component={Teachers} />> </Router> ), document.getElementById('root')); <Route component={App}> <oute path="/" component={Home} /> <Route path="/courses" component={Courses} /> <R chers" com ponent={Teachers} /> </Route> <Route path="/" component={Home} /> <Route path="/courses" component={Courses}> <Route path="/html" component={HTML} /> <Route path="/css" component={CSS} /> </Route> … <Route path="html" component={CourseContainer} data={CourseList.HTML} /> … // index.js import CourseContainer from './CourseContainer'; import CourseList from './data';
  32. Rendering content // CourseContainer.js class CourseContainer extends Component { render()

    { let courseList = this.props.route.data; let courses = courseList.map((course) => { return <Course … > … }); return ( <div> { courses } s.pr </div> ); } }
  33. Defining parameters ReactDOM.render(( <Router history={browserHistory}> <Route component={App}> <Route path="/" component={Home}

    /> <Route path="/courses" component={Courses} /> Route path="/teachers" component={Teachers} />> </Router> ), document.getElementById('root')); <Route component={App}> <oute path="/" component={Home} /> <Route path="/courses" component={Courses} /> <R chers" com ponent={Teachers} /> </Route> <Route path="/" component={Home} /> <Route path="courses" component={Courses}> <Route path="/html" component={HTML} /> <Route path="/css" component={CSS} /> </Route> <Route path="featured/:topic/:name" component={Featured} /> <Route path="html" component={HTML} /> … // index.js … import Featured from './Featured';
  34. You can use what's passed through parameters as data in

    your components with this.props.params
  35. Rendering params … const Featured = props => <p>{props.params.name} enjoys

    teaching {props.params.topic}!</p> export default Featured; // Featured.js
  36. “404” error route ReactDOM.render(( <Router history={browserHistory}> <Route component={App}> <Route path="/"

    component={Home} /> <Route path="/courses" component={Courses} /> ="/teachers" component={Teachers} />> </Router> ), document.getElementById('root')); <Route component={App}> <Route path="/courses" component={Courses} /> <R chers" com={Teachers} /> </Route> <Route path="/" component={Home} /> <Route path="courses" component={Courses} /> <Route path="teachers" component={Teachers} /> <Route path="/html" component={HTML} /> <Route path="*" component={NotFound} /> // index.js … import NotFound from './NotFound';
  37. Route redirect // index.js ReactDOM.render(( <Router history={browserHistory}> <Route component={App}> <Route

    path="/" component={Home} /> <Route path="/courses" component={Courses} /> Route path="/teachers" component={Teachers} /> < /Route> </Router> ), document.getElementById('root')); <Route component={App}> <Route path="/" component={Home} /> <Route path="/courses" component={Courses} /> <R oute path ="/teachers" component={Teachers} /> </Route> <Route path="/" component={Home} /> <Route path="/courses" component={Courses}> <Route path="/html" component={HTML} /> <Route path="/css" component={CSS} /> < Route path="/javascript" component={JS} /> </Route> <Route path="/teachers" component={Teachers} /> <IndexRoute component={HTML} /> <Route path="html" component={HTML} /> <Route path="css" component={CSS} /> <Route path="javascript" component={JS} /> … import { Router, Route, browserHistory, IndexRedirect } from 'react-router'; <IndexRedirect to="html" />
  38. As you add more routes, it’s easier to work with

    routing if you move routes into their own file.
  39. Organizing routes <Router history={browserHistory}> <Route component={App}> <Route path="/" component={Home} />

    <Route path="/courses" component={Courses}> <IndexRedirect to="html" /> <Route path="html" component={HTML} /> <Route path="css" component={CSS} /> <Route path="javascript" component={JS} /> </Route> <Route path="/teachers" component={Teachers} /> <Route path="*" component={NotFound} /> </Route> </Router> const routes = ( ); export default routes; //router.js
  40. Location & Match • Location: Data representing where a visitor

    is (or wants to go) in your app • Match: Turns a location into UI
  41. Declare routes from anywhere! … import App from './App'; ReactDOM.render(

    <App />, document.getElementById('root') ); // index.js
  42. BrowserRouter // App.js import { BrowserRouter } from 'react-router'; class

    App extends Component { render() { return ( <BrowserRouter> </BrowserRouter> ); } } <div> <h1>Course App</h1> <ul className="main-nav">…</ul> <div className="main-content">…</div> </div>
  43. Match a URL path to a component // App.js import

    { BrowserRouter, Match } from 'react-router'; class App extends Component { render() { return ( <BrowserRouter> </BrowserRouter> ); } } <div> <h1>Course App</h1> <ul className="main-nav">…</ul> <div className="main-content">…</div> </div> <Match />
  44. Match a URL path to a component // App.js <BrowserRouter>

    <div> … <Match pattern="" component={} /> </div> </BrowserRouter>
  45. Match a URL path to a component // App.js <BrowserRouter>

    <div> … <Match pattern="/" component={Home} /> </div> </BrowserRouter> <Match pattern="/teachers" component={Teachers} /> <Match pattern="/courses" component={Courses} />
  46. Match only if pattern matches path exactly // App.js <BrowserRouter>

    <div> … <Match exactly pattern="/" component={Home} /> </div> </BrowserRouter> <Match pattern="/teachers" component={Teachers} /> <Match pattern="/courses" component={Courses} />
  47. Nested routes // App.js … class App extends Component {

    render() { return ( <BrowserRouter> <div> <h1>Course App</h1> <ul className="main-nav">…</ul> <div className="main-content">…</div> <Match exactly pattern="/" component={Home} /> <Match pattern="/teachers" component={Teachers} /> <Match pattern="/courses" component={Courses} /> </div> </BrowserRouter> ); } }
  48. Nested routes URL Component / App -> Home /teachers App

    -> Teachers /courses App -> Courses
  49. Render a miss // App.js <BrowserRouter> <div> … </div> </BrowserRouter>

    <Match pattern="/" component={Home} /> <Match pattern="/teachers" component={Teachers} /> <Match pattern="/courses" component={Courses} /> <Miss component={NotFound} />
  50. URL params <BrowserRouter> <div> … </div> </BrowserRouter> <Match pattern="/" component={Home}

    /> <Match pattern="/teachers" component={Teachers} /> <Match pattern="/courses" component={Courses} /> <Match pattern="/featured/:topic/:name" component={Featured} /> <Miss component={NotFound} /> // App.js
  51. Passing props <Match pattern="/" render={ () => <Home title="Welcome!" />

    } /> <Match pattern="/teachers" component={Teachers} /> <Match pattern="/courses" component={Courses} /> … // App.js
  52. Passing props <Match pattern="courses/html" render={ () => <CourseContainer data={CourseList.HTML} />

    } /> <Match pattern="courses/css" render={ () => <CourseContainer data={CourseList.CSS} /> } /> <Match pattern="courses/javascript" render={ () => <CourseContainer data={CourseList.JS} /> } /> … // Courses.js
  53. Use pathname for patterns & relative links const Courses =

    ({ pathname }) => ( <div> <h1>Courses</h1> <ul> <li><Link to={`${pathname}/html`}>HTML</Link></li> <li><Link to={`${pathname}/css`}>CSS</Link></li> <li><Link to={`${pathname}/javascript`}>JavaScript</Link></li> </ul> … <Match pattern={`${pathname}/html`} render={…} /> <Match pattern={`${pathname}/css`} render={…} /> <Match pattern={`${pathname}/javascript`} render={…} /> </div> ); // Courses.js
  54. Route redirects const Courses = ({ pathname }) => (

    <div> <h1>Courses</h1> <ul>…</ul> … <Match pattern={`${pathname}/html`} render={…} /> <Match pattern={`${pathname}/css`} render={…} /> <Match pattern={`${pathname}/javascript`} render={…} /> </div> ); // Courses.js <Redirect to={`${pathname}/html`} />
  55. Migrating to v4 • Move route configuration to your component

    render methods • Change <route> to <match> • Change path to pattern
  56. Find what works for you, your project and your team.

    Develop a style and approach and be consistent about it.