Day 10: Routing in Noteherder

Wednesday, July 12, 2017

Lecture Videos

Morning: Day 10, part 1

Afternoon: Day 10, part 1

Topics

React Router

  • Redirect component
  • Passing props to components in Routes

Deployment of React app with routing

  • github pages
  • firebase

Examples

React Router

Redirect component

The Redirect component provided by React Router allows us to cause the user to navigate to a new location. Just drop in a Redirect component and pass it a to prop to tell it where to redirect, and you’re good to go!



<Redirect to='/widgets' />


A common use case for a Redirect is to send a user to different locations based on whether they are logged in or not.



import { Route, Redirect } from 'react-router'

<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>


The code above translates to: “If the path is at the root route (‘/’), redirect to ‘/dashboard’ if the user is logged in. Otherwise, render the PublicHomePage.”

Passing props to routed components

Here’s a basic Route that renders a Stuff component when the path matches '/stuff':



<Route path="/stuff" component={Stuff} />


When Stuff is rendered, it will automatically receive props from the router that include match, history, and location. But what if we want to pass additional props to Stuff? It turns out, we can use the render prop for Route instead, which allows us to pass additional props when the anonymous function returns some JSX.



<Route path="/stuff" render={(props) => (
  <Stuff name="Bob" {...props} />
)} />


In this example, the anonymous function in the render for the Route receives an argument of props (which includes match, history, and location). Our render method returns some JSX - specifically, the <Stuff /> component. We pass along our existing props to Stuff via Object spread, as well as an additional name prop.

Deployment of a React app with routing

Now that Noteherder has routing, deployment gets a bit more complicated. Our app is a single-page application, so the server that our app is deployed to needs to always return index.html (the one page in our single-page app). However, if we type https://{yourdomainhere}/notes in the address bar, the server will try to find a file called notes.html to send back (which it won’t find, of course). So how do we get it to always respond with index.html and let our client-side router handle the routing? There are a few options:

  1. Configure the server to always return index.html, no matter what is requested. (ideal solution)
  2. Use HashRouter instead of BrowserRouter
  3. Make a custom 404 page that is a copy of index.html.

Github Pages

Github Pages does not allow for server configuration, so option #1 is out. We can, however, do options #2 or 3. For our in-class example, we chose to use HashRouter to solve this problem. Simply swap out BrowserRouter for HashRouter in index.js and re-deploy. This will make your in-app routes appear after a # in the URL, which prevents the server from trying to respond with a different page. For example, https://myusername.github.io/noteherder/notes becomes https://myusername.github.io/noteherder/#/notes when using HashRouter.

index.js


  
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter as Router, Route } from 'react-router-dom'


import './index.css'
import App from './App'
import registerServiceWorker from './registerServiceWorker'

ReactDOM.render(
  <Router>
    <Route component={App} />
  </Router>, 
  document.getElementById('root')
)
registerServiceWorker()

  
  

Firebase

Firebase does allow for the server to be configured to always return index.html, so that is the option we chose during class. To do so, we first need to install Firebase’s CLI tools.

user@localhost ~
 
npm install -g firebase-tools

Once the Firebase tools are installed, we can use them to login, initialize a firebase project, and deploy. (Note, make sure you have made a production build with npm run build before deploying)

user@localhost ~
 
firebase login
firebase init
firebase deploy

Firebase Init

firebase init will prompt you to answer a bunch of questions about how you want to configure the app you are deploying. For more information about how to answer those questions, check out the create-react-app README here

Projects

Noteherder: Morning | Afternoon

Homework

  • Add an updatedAt field to notes (updating its value every time you save the note).

Super Mega Bonus Credit

  • Sort the notes in the list with the most recently updated at the top.