Before we get cracking, let’s start with a quick recap. We are building a basic app that mimics the functionality that we would typically find on most SaaS websites when subscribing to one of their particular product plans, and we are using Stripe to handle the online payment processing.

As I mentioned last time around, the technologies (or tech stack) we’ll be using to build out this experience are the following:

Serverless + AWS Lamda — used to deploy a cloud function that will handle creating a new customer account in Stripe for a user, and then subscribing them to the selected product plan. React — used to build out a simple UI that will allow us to create our Stripe account and choose a product plan.

In Part 1, I gave a walkthrough on how to create a lambda service using the serverless framework, how to get it running locally, and finally deploying it to AWS Lambda. In this post, we’ll be moving on to build our frontend application with React.

Create React App

We’re going to be using Facebook’s create-react-app boilerplate for this task. You can go ahead install it by following the commands below to get your React app up and running:

$ npx create-react-app react-stripe-subscriptions-frontend

$ cd react-stripe-subscriptions-frontend

$ npm start

Now that we’ve got that first step out of the way, we’ve got some dependencies to install. If you plan on using npm as your package manager, then you should delete your yarn.lock file to avoid having 2 lock files.

I want to make use of TypeScript’s static type checking, as well as install reactstrap and styled-components for styling purposes.

$ npm i --save bootstrap reactstrap react-stripe-checkout styled-components

$ npm i --save-dev typescript @types/react @types/react-dom @types/reactstrap @types/styled-components

Got that done? Cool, now let’s bring TypeScript into the playing field by modifying our index.js and App.js file. To do this, change the extensions for these two files to .tsx, and then update each of the file contents to match the following:

The index.tsx file

import * as React from "react"; import * as ReactDOM from "react-dom"; import App from "./App"; import * as serviceWorker from "./serviceWorker"; /** Bootstrap */ import "bootstrap/dist/css/bootstrap.css"; ReactDOM.render(<App />, document.getElementById("root")); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();

The App.tsx file

import * as React from "react"; const App: React.FC<{}> = () => { return <div>Subscribe to product</div>; }; export default App;

Once you’re done with that, you can delete the unused boilerplate code like index.css, App.css and logo.svg. Our app should compile just fine, and running the local server should render a blank page to the DOM with nothing but the basic text in our App.tsx file, ‘Subscribe to product’.

Building Out The Product Plans Page

It’s nothing fancy, but the page below is what we’re going to be developing, along with the functionality to subscribe to any one of these plans. You can add as many packages as you want depending on the number of pricing plans you created from the Stripe dashboard of your test account.

Inside the src directory, we’re going to have the following folder structure:



├── Components

├── Theme

└── Utils ├── @types ├── Components├── Theme└── Utils

Inside the Theme folder, create the following files:

Colors.ts

const Colors = { aqua: "#33cccc", grey: "#666", lightGrey: "#ccc", red: "#cc0000" }; export default Colors;

index.ts

import Colors from "./Colors"; export { Colors };

Next up, inside the Components folder, create a Styles.tsx file which will contain our styled components.

We want to be able to handle displaying of any errors that our app may encounter, so I’m going to create a custom hook (ErrorHandler.tsx) that we’ll be using in our main functional component, and after that I’ll create a presentation component (ErrorMessage.tsx) that will receive the error message to be shown to the user. Both files will live inside the Components folder.

ErrorHandler.tsx

ErrorMessage.tsx

Moving on to the Utils folder, we’re going to create two files:

API.ts — contains a function to handle making a POST request to our lambda function. Consts.ts — contains our Stripe publishable key and the details of our product plans and their respective id’s from our Stripe account. Click here if you’re wondering how to get the id of each of the product pricing plans you created in the Stripe dashboard.

API.ts

Consts.ts

export type Product = { id: string; name: string; description: string; users: string; price: number; }; /** Stripe publishable key */ export const STRIPE_PUBLISHABLE_KEY = ""; /** Stripe product plan ids */ const STANDARD_PRODUCT_ID = ""; const PREMIUM_PRODUCT_ID = ""; const ENTERPRISE_PRODUCT_ID = ""; /** Stripe product plans */ export const PRODUCT_PLANS: Array<Product> = [ { id: STANDARD_PRODUCT_ID, name: "Standard", description: "For small teams.", users: "4 users", price: 10 }, { id: PREMIUM_PRODUCT_ID, name: "Premium", description: "For medium sized teams.", users: "20 users", price: 25 }, { id: ENTERPRISE_PRODUCT_ID, name: "Enterprise", description: "For large teams.", users: "100+ users", price: 50 } ];

Another thing to consider is how to handle the response we get back from the Stripe API. We don’t want to have to keep checking the log in our browser so let’s install a package that will display a notification for us letting us know if our subscription was successful.

$ npm i --save react-toast-notifications

At the time of me writing this post, this package doesn’t have any type definitions, so we’ll need to create a “.d.ts” file for it inside the @types folder. These files are used to provide typescript with type information.

react-toast-notifications.d.ts

The content of this file will be as follows:

declare module "react-toast-notifications";

Inside our Components folder, create a SubscribeToProduct.tsx file which will contain our main component that brings it all together.

Last but not least, let’s update our App.tsx file and import the SubscribeToProduct component into it. We’re also going to wrap our app in a ToastProvider HOC which will provide context to our app.

import * as React from "react"; import { ToastProvider } from "react-toast-notifications"; import SubscribeToProduct from "./Components/SubscribeToProduct"; /** Styling */ import { AppWrapper } from "./Components/Styles";

const App: React.FC<{}> = () => { return ( <AppWrapper> <ToastProvider placement="bottom-center"> <SubscribeToProduct /> </ToastProvider> </AppWrapper> ); }; export default App;

And that, ladies and gentlemen, is the finishing touch to the frontend of our application. You can go ahead and run npm start or yarn start, depending on the package manager you have been using for this project. While you’re it, go ahead and get the AWS Lambda and API Gateway emulation running on your local machine in a different port with serverless-offline. Alternatively, you can post requests to your deployed lambda service.

Here’s a list of test cards provided by Stripe that you can use when testing out your subscription functionality.

That brings us to the end of our short journey on how to build out a basic product plan subscription flow 😃. I hope that it will come in handy next time you’re working on similar functionality, whether or not your choice of technologies matches the tech stack chosen for this particular tutorial.

Happy coding! 👨‍💻

You can find the code for this post at: https://github.com/LukeMwila/react-stripe-subscriptions-frontend

If you enjoyed the post, feel free to buy me a coffee here ☕️ 😃 .