React Router

“Complete freedom is not what a trail offers. Quite the opposite; a trail is a tactful reduction of options.”
Robert Moor, On Trails: An Exploration

How browser navigation works

History API

history.back() // or history.go(-1)
history.forward() // or history.go(1)
history.go(n) // relative to current. 0 to refresh. 
history.pushState(state, title, url) 
history.replaceState(state, title, url)

🍕 Routing types

Static routes

Declare routes before any rendering takes place

Example

const appRoutes: Routes = [
  { path: 'crisis-center',
    component: CrisisListComponent
  },
  { path: 'hero/:id',
    component: HeroDetailComponent
  },/*...*/];

@NgModule({
  imports: [ RouterModule.forRoot(appRoutes) ]
}) export class AppModule { }

Example

app.get('/', handleIndex);
app.get('/invoices', handleInvoices);
app.get('/invoices/:id', handleInvoice);
app.get('/invoices/:id/edit', handleInvoiceEdit);

app.listen();

Dynamic routes

Declare routes as app is rendering

React router v4

Everything is a component

import { BrowserRouter, Route } from 'react-router-dom';

const App = () => (
  <BrowserRouter>
    <div>
      <Route path="/tacos" component={Tacos}/>
      <Route path="/nachos" component={Nachos}/>
      <Route path="/burritos" component={Burritos}/>
    </div>
  </BrowserRouter>
);

Nested routes



const Tacos: React.SFC = () => (
    <Route
      path="/tacos/carnitas" // absolute route
      component={Carnitas}
    />
);

export Tacos;

Nested routes

import { withRouter, RouteComponentProps } from 'react-router';

const Tacos: React.SFC<RouteComponentProps<TacosProps>>  = (props) => (
    <Route
      path={props.match.url + '/carnitas'}
      component={Carnitas}
    />
);

export const TacosWithRouter = withRouter(Tacos);

Links

// as a component
import { Link } from 'react-router-dom';

const GetTacos: React.SFC = () => (<Link to="/tacos">
  Get me some tacos!
</Link>);

Links

// using history api
import { withRouter, RouteComponentProps } from 'react-router';

interface Props {/*...*/}

const GetTacos: React.SFC<RouteComponentProps<Props>> = (props) => (
    <button onClick={() => props.history.push(props.match.url + '/tacos')}>
        Get me some tacos!
    </button>);

export const GetTacosWithRouter = withRouter(GetTacos);

🛠 Try it

  • Add main page to the game with 2 buttons: Start game and Info
  • Start game navigates to game component and starts a new game
  • Info navigates to game info component with details about the app