This is the client side notes for my first AWS Serverless infrastructure. API notes are here

AWS Amplify

AWS Amplify is a set of tools and services that enables mobile and front-end web developers to build secure, scalable full stack applications, powered by AWS.

I leveraged three modules of Amplify:

  1. Auth (Cognito User Pool and Cognito Identity Pool)
  2. Storage (S3)
  3. API (API Gateway)

Configuration

At the start of the programme, I need to specify the configuration of Amplify. In this project, I did it in src/index.js which runs upon loading the client side.

The corresponding Serverless Stack chapter is Configure AWS Amplify.
The corresponding Amplify Docs page for JavaScript Amplify Libraries is Configure Amplify Categories. There are top-level and scoped configurations.

Using Amplify

Once Amplify is configured, it is able to make requests to AWS resources on the client’s behalf. Just like the API handlers, Amplify could use the Cognito Identity session to access the resources private to the current user.

react-route-dom

useLocation

The useLocation hook returns a Location object that represents the current URL.

The Location interface is explained very well in the MDN docs. It has these parts:

  1. href the whole URL
  2. protocol http/https
  3. host localhost:3000
  4. pathname /foo/bar
  5. search ?q=baz
  6. hash #header1

BrowserRouter

A that uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL.

You wrap the <App/> within the <BrowserRouter> to have access to the <Switch>/<Route>/<Link> etc.

Switch and Route

  • <Switch> is unique in that it renders a route exclusively. It will look through the <Route>s from top to bottom and render the first match. We could create a <NoMatch> and put it into the last <Route> as a 404 page.
  • In contrast, if we don’t wrap the <Route>s into <Switch>, every <Route> that matches the location renders inclusively. This is a delicate design to enable us to compose our <Route>s.

Redirect

Rendering a will navigate to a new location. The new location will override the current location in the history stack, like server-side redirects (HTTP 3xx) do. So it is a good way to elegantly route unauthenticated user away from locations that require authentication, and they will not get back to the authenticated locating by hitting the “Back” button.

AuthenticatedRoute and UnauthenticatedRoute

There are some pages that we only want the user to see when they are not authenticated, for example, /signup and /login; There are also pages that we only want authenticated user to see, for example, /notes/{id}.

To achieve this, we can wrap Route into AuthenticatedRoute and UnauthenticatedRoute components, and ensure the user is redirected elegantly if they wade to somewhere they don’t belong.

The step-through guideline in Serverless Stack is Create a Route That Redirects.

Extract query string with given name by Regex

This is a pretty cool usage of RegExp and its exec method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function querystring(name, url = window.location.href) {
name = name.replace(/[[]]/g, "\\$&");

const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)", "i");
const results = regex.exec(url);

if (!results) {
return null;
}
if (!results[2]) {
return "";
}

return decodeURIComponent(results[2].replace(/\+/g, " "));
}

Given name of value "redirect" and url of value "http://localhost:3000/login?redirect=/notes", the result of regex.exec(url) is:

1
2
3
4
5
6
7
8
[
'?redirect=/notes/26e9b6b0-fb14-11ea-bcae-ef1bd0468689',
'=/notes/26e9b6b0-fb14-11ea-bcae-ef1bd0468689',
'/notes/26e9b6b0-fb14-11ea-bcae-ef1bd0468689',
index: 27,
input: 'http://localhost:3000/login?redirect=/notes/26e9b6b0-fb14-11ea-bcae-ef1bd0468689',
groups: undefined
]

The array of the first results are refined step by step with the ()s specified in the RegExp construction: "[?&]" + name + "(=([^&#]*)|&|#|$)".

The decodeURIComponent() function decodes a Uniform Resource Identifier (URI) component previously created by encodeURIComponent or by a similar routine. %20%28correct%29 decoded -> (correct)