Skip to content

Instantly share code, notes, and snippets.

@geekysam7
Last active August 1, 2020 09:46
Show Gist options
  • Save geekysam7/bee35670c3c5caa866b2443aa3b5e1e0 to your computer and use it in GitHub Desktop.
Save geekysam7/bee35670c3c5caa866b2443aa3b5e1e0 to your computer and use it in GitHub Desktop.

🌟 Setting Up Routing 🌟

SPA

The idea behind a single page application is a single HTML file. We want to show the user different pages for different paths.
This is possible by using a router package through which we can render different pages for different paths.

Router Package

It does 3 main things:

  • Parses URL/Path
  • Read config: which path are supported and what happens if user visists it.
  • Render/Load appropriate JSX/Component.

Installation

We need two packages:

yarn add react-router react-router-dom
  • react-router: has logic.
  • react-router-dom: for rendering to dom. For web development react-router-dom is enough as it wraps react-router.

Setting Up

Inside your app.js or index.js file:

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

//code
return (
  <BrowserRouter> 
    <Components/>
  <BrowserRouter>
)

Wrap the component that you want to have the routing functionality with BrowserRouter component.

Rendering Routes

We use Route Component from 'react-router-dom' Package for managing the routes.
It's time to render routes, so at look the different ways of using Route.

//First import
import { Route } from 'react-router-dom';

//Inside return statement:

<Route path="/" render={ () => <h1>Hello.</h1> } />
//does my path start with '/'.

<Route path="/" exact render={ () => <h2>Exact Match</h2> />
//does my path completely matches '/'.

//Loading components

<Route path="/" exact component={rederMe} />
//renderMe is an component we pass which gets rendered at '/'.

Using Link to prevent reloading

Link replaces the anchor tags and handles click internally.

import { Link } from 'react-router-dom';
//avoid a as it will make page reload
<a href="/">Home</a>

//Use Link for preventing reloading
<Link to="/"> Home </Link>
<Link to={{
  pathName:"/new-post",
  hash: "#submit",
  search: "?q=1"
}}> New Post </Link>

How Routing Works?

The route component passes the props to it's component. Inside any component loaded via Link write this:

componentDidMount() {
  console.log(props);
}

We can use this props to do all sorts of things. But this props do not get passed down in the component tree.
To access them we have two methods:

  • use {...this.props}
  • Wrap the export with withRouter ex:
import { withRouter } from 'react-router-dom';
//Code
export default withRouter(Post);
//making the component route aware.

Absolute vs Relative Path

Absolute path is always appended to our domain.

<Link to="/">Home</Link>
//domain.dev/
<Link to="/new-post">New Post</Link>
//domain.dev/new-post

to prop by default is an absolute path.
Relative path: Appending the path at the end of the current path.

<Link to={{
  pathName: this.props.match.url + '/new-post'
}}> New Post </Link>

Styling the active route

For styling we can use NavLink component instead of Link as it comes with more features.

  • Replace your Link components with the NavLink components.
  • using the default active class it has:
//inside navbar class
<NavLink to="/" exact>Home</NavLink>
.navbar a.active {
  color: orange;
}
/* NavLink gets converted to a */

Ofcourse we can change the class name why use the default name -_-

<NavLink to="/new-post" exact activeClassName="SuperSaiyan">New Post</NavLink>

Instead of working with css we can use the activeStyle prop

<NavLink to="/new-post" exact activeStyle={{ color: '#fa923f'}}>New Post</NavLink>

Passing Route Parameters

Creating a variable route parameter which gets replaced dynamically.

Note: Remember the order of writing Route component is important as they get executed in the order they are written.

<Route path="/:id" exact component=renderMe />

Now remember any route with path /something also falls in the above category. for distinguishing them:
Keep the order correct

<Route path="/something" exact component={renderMe} />
<Route path="/:id" exact component={renderMe} />

Extracting Route Parameters

We used :id in the path above but what does it mean?
It helps us to extract information from the props that are passed by react-router. The id value can be extracted in renderMe component as this.props.match.params.id.

Using Switch

Switch tells the react router please load only one of the routes! The first one that matches the route.

<Switch>
  <Route path="/" exact component={Posts}>
  <Route path="/something" exact component={renderMe} />
  <Route path="/:id" exact component={renderMe} />
</Switch>

Navigating Programmatically

The react-router props has an history object which has method such as:

  • push
  • go
  • goBack
  • goForward
  • listen
  • replace
  • block Which does exactly what the method name says.
    Navigation is just a stack of pages so these methods ( buttons as we say ) work with the stack.
    ex:
//handles onClick event on a post.
postHandler = (id) => {
  this.props.history.push({pathName:'/' + id});
}
//the page is pushed in the stack.

Nested Routes

Use Relative paths instead of hard coded paths to avoid non rendering of components.

this.props.match.url //the url we loaded thus far.

And use componentDidUpdate for rendering changes if the component is already loaded through routing.

Redirecting Requests

Redirect is just like Route it takes two props from and to or just give a to prop.

import { Redirect } from 'react-router-dom'
//code
<Redirect from="/" to="posts" />

This is how we can redirect the users. We can also do conditioal redirects like when a submit button is clicked etc.
Using history prop to redirect.

this.props.history.replace('/posts'); 
//or
this.props.history.push('/posts');

Guard

Useful when we want to check the user is authenticated or not. We can maintain a state like auth which is a boolean and we can conidtionally render the component if user is authenticated.
ex:

{this.state.auth ? <Route path="/new-post" component={renderMe} />

Handling 404 case

Inside the switch component at the last we can write a Route component without a path prop:

<Switch>
  <Route render={() => <h1>Not Found</h1> }
</Switch>

Loading Routes Lazily

Why to download the code upfront?
When working with large applications you don't to send the whole application upfront to the user.
The technique of downloading only what you need is called code splitting or lazy loading.
For this to work we need a higher order component. ex:

//A higher order component
import React, { Component } from 'react';
const asyncComponent = (importComponent) => {
  return class extends Component {
    state = {
      component: null,
     }
     
    componentDidMount () {
      importComponent()
        .then(cmp => {
          this.setState({ component: cmp.default });
         });
    }
    
    render() {
      const C = this.state.component;
     
      return C ? <C {...this.props} /> : null;
    }
}

export default asyncComponent;

Now for lazy loading we don't want to load the components ( importing ) as they will be included in the global bundle.

Note: It is recommended to use create-react-app so the webpack configuration is already setup.

import asyncComponent from '../hoc/asyncComponent';
//import NewPost from './NewPost/NewPost';

const AsyncNewPost = asyncComponent(() => {
  return import('./NewPost/NewPost'); //special dynamic importing syntax.
  //gets imported only if AsyncNewPost is used somewhere.
}

Webpack creates a small bundle which is sent when needed.

React Suspense

No need to creat asyncComponent hoc. React offers React.lazy() for dynamic loading of the components.

import React, { Component, Suspense } from 'react';
const Posts = React.lazy(() => import('./containers/Posts'));

//now inside your return statement:
<Route path="/posts" render={() => {
  <Suspense fallback={ <div>Loading...</div> }
    <Posts />
  </Suspense>
}}

fallback prop takes care of the time in between.
Suspense is a very useful component as it can be used withour Router as well for doing lazy loading.

Note: It only works for client side rendered application. For small projects suspense it is not needed.

Routing and Server

When deploying our app to the server, the server does not know the routes it is the react app which knows it.
The development server is configured already so we won't see 404 errors there but during deployment it is important to set this up.

  • Always load index.html
  • If you are serving your app from domain.dev/my-app then you need to configure the base path which is very easy to do.
<BrowserRouter bassname="/my-app">
  //code
</BrowserRouter>

By default basename is set to /.

Author

@geekysam7

@addyson-martin
Copy link

Very nice broh πŸ₯°πŸ’˜πŸ’˜πŸ’˜πŸ’˜

@Prady2006
Copy link

Best gist ever for fellow frontend developers .Keep up the good work geekysameer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment