Building a Progressive Web App with React 18

Building a Progressive Web App with React 18

by Amazing Enyichi Agu

When some websites get visited on a smartphone, the website prompts the user to install itself into the user's device like an app. When "downloaded" into the user's device, these websites have almost the same features a native mobile app would. They even have icons that can be viewed on the user's home screen. When a website has been built in such a way, then we say the website is a Progressive Web App.

What is a Progressive Web App (PWA) and how does it work?

A progressive Web App is a website that can behave like a native app. This is possible due to the additional customizations done to the Web app or website, which gives these capabilities. Some features a PWA is capable of include push notifications, the ability to work on Android and IOS without much difference, a regular icon on the home screen of the user's device like a standard app would, and the ability to work offline.

Here are some reasons why Progressive Web Apps are to be chosen or used by developers.

  • Lower Costs: Building a native mobile app or desktop app requires a budget for hiring a developer. But with PWAs, a mobile developer is not needed as a website can be converted straight away into a Progressive Web App,

  • Time Saved: A PWA saves time that would've been spent building a mobile app. The same codebase can be shared across multiple platforms and still look and feel good.

  • Lightweight: PWAs are lightweight, not heavy and bulky. This helps the web app have faster loading times and optimum memory utilization.

  • Cross-Platform: PWAs are cross-platform. They run in Android, IOS, Windows, and even MacOS, accessible with any device with a browser.

  • Fast Update: A Progressive Web App does not need an update to be installed for it separately on any platform it is on. It updates on its own since it technically is a website.

In this article, we will be building a simple note-taking app with React JS and then making it a Progressive Web App.

Creating the project

We will use React 18 (the latest version of React JS) to build this project. Remember, we need to have Node version 14.0.0 (or higher) and npm version 5.6 or more to use React 18.

npx create-react-app notes

And then we have our react notes app load.

After it is installed, we will run:

cd notes
npm start

After this, we can also proceed to open our newly created react app on our favorite code editor,

Creating the Page

And now, we will create our homepage with contain our App component. In the index.js, we have:

import React from "react";
import App from "./App";
import { createRoot } from "react-dom/client";
const container = document.getElementById("root");
const root = createRoot(container);

root.render(<App />);

And in our App.js we have

import React, { useState } from 'react';
import './style.css';

export default function App() {
  return (
    <div>
      <h1>My Notes</h1>
      <input type="text" />
      <button>Save</button>
    </div>
  );
}

And now we have this displayed on our page:

First version of the page

Creating the Notes Component

We will create a Notes component that will display any available notes. The component will be inside a folder, and the folder will be created inside the src folder and called components.

After that, we will create a file called Notes.js inside the components folder and create a simple function that loops through available data served in the props, creating different p elements.

Component file structure

Inside the Notes.js file, we have:

import React from 'react';

function Notes({ data }) {
  return data.map((value) => <p>{value}</p>);
}

export default Notes;

This means that our Notes component will always take the parameter data. Now to import it into our App.js, we have:

import React, { useState } from 'react';
import Notes from './components/Notes';
import './style.css';

export default function App() {
  return (
    <div>
      <h1>My Notes</h1>
      <input type="text" />
      <button>Save</button>
      <Notes/>
    </div>
  );
}

Remember, our Notes component needs parameter data. We will create states for the data that will update whenever the save button is clicked.

import React, { useState } from 'react';
import Notes from './components/Note';
import './style.css';

export default function App() {
  let [list, setList] = useState([]);
  let [newNote, setNewNote] = useState('');

  function addNote() {
    let addedNote = list.concat(newNote);
    setList(addedNote);
    setNewNote('');
  }

  function handleChange(e) {
    setNewNote(e.target.value);
  }

  return (
    <div>
      <h1>My Notes</h1>
      <input type="text" value={newNote} onChange={handleChange} />

      <button onClick={addNote}>Save</button>
      <Notes data={list} />
    </div>
  );
}

And now, we should be able to save some notes with our app.

The app, working

Registering our Service Worker

What is a service worker? A service worker is just a required JS program for our app to be a Progressive Web App.

So, to use a service worker, we will have to register it on our index.js, so we import serviceWorker.js into our index.js.

index.js:

import React from "react";
import App from "./App";
import * as serviceWorker from "./serviceWorker"
import { createRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = createRoot(container);

root.render(<App/>);

serviceWorker.register():

Editing our manifest.json file

The final step to making our app a PWA is to change some things in our manifest.json file. We will set our icons and other options available.

{
  "short_name": "My Notes App",
  "name": "Notes Progressive Web Application",
  "icons": [
    {
      "src": "icon.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": "./",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}

And finally, we have a PWA app working that can run on any device like a native app.

Open Source Session Replay

OpenReplay is an open-source alternative to FullStory and LogRocket. It gives you full observability by replaying everything your users do on your app and showing how your stack behaves for every issue. OpenReplay is self-hosted for full control over your data.

replayer.png

Happy debugging for modern frontend teams - start monitoring your web app for free.

Conclusion

Progressive Web Applications will continue to be used to enhance the mobile experience of websites in the nearest future as it is a cheaper alternative to building native mobile apps from scratch - and React JS happens to come with some functionalities for converting a React app straight into a Progressive Web App.

This project's source code can be found in Stackblitz.