Files
web-log/container/site/content/posts/react-app-resurrection/index.md
T
nicholas 2e9bd0e409
Build & Push Hugo Site Image / Build & Push Image (push) Successful in 9s
Build & Push Hugo Site Image / deploy (push) Successful in 16s
add tags, descriptions to posts (#38)
2026-08-05 16:24:33 -05:00

8.3 KiB

+++ categories = ["software"] tags = ["react","typescript","javascript"] date = 2025-04-12T00:00:00-06:00 description = "Reviving an old React storage application by replacing React Scripts with Vite, updating packages, and migrating JavaScript to TypeScript." draft = false slug = "react-app-resurrection" title = "⚛️ React App Resurrection" author = "nicholas" +++

Project git repo

A few years ago the company I work for explored the idea of rewriting older ASP.NET and Backbone.js features in a more modern web framework. Between the two contenders, React and Vue, the development team was leaning toward Vue. Each developer went off and built a small feature or two using Vue to get a sense for it before we eventually committed to rewriting with it. I raised no objections to the decision because it did not matter to me, and I like Vue just fine.

Eventually, though, I wanted to try building something with React, so I contrived the simplest possible project that would force me to understand at the very least the fundamentals of React. This is why I created this in the first place.

The app is a simple CRUD app that manages boxes, which can contain items. I rewrite the app with TypeScript and clean it up a little bit.

Technology Stack

I am using the MERN tech stack:

  • MongoDB (Database)
  • Express.js (Backend framework)
  • React (Frontend framework)
  • Node.js (Backend runtime)

There are a couple main goals I want to accomplish:

  1. Get the app working
  2. Upgrade to Vite from Create React App
  3. Update Packages
  4. Typescript rewrite, refactor using better practices

1. Get the App Working

The first thing I will do is get the database working. This is straightforward minus a small hiccup: my server runs on an Intel Pentium Gold G5400, and MongoDB versions 5+ cannot run without the AVX instruction set extension, which is regrettably absent in the spec sheet.

{{< image src="images/pentium-gold-g5400-instruction-set-extensions.jpg" caption="Pentium Gold G5400 Instruction Set Extensions - AVX missing" >}}

So I will use a very old version of mongodb (mongo:4.4.6) to get the app working.

Here is my compose.yml file. The container also includes Mongo Express which will allow me to manage my databases with a web interface rather than manage it through the command line. The environment variables are stored in .env file.

compose.yml

services:
  mongo:
    container_name: mongo-db
    image: mongo:4.4.6
    networks:
      - mongo-network
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
    ports:
      - 27017:27017

  mongo-express:
    container_name: mongo-express
    image: mongo-express
    networks:
      - mongo-network
    restart: always
    ports:
      - 8999:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: ${ME_CONFIG_MONGODB_ADMINUSERNAME}
      ME_CONFIG_MONGODB_ADMINPASSWORD: ${ME_CONFIG_MONGODB_ADMINPASSWORD}
      ME_CONFIG_MONGODB_URL: mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017/
      ME_CONFIG_BASICAUTH: false

networks:
  mongo-network:
    name: mongo-network

.env

MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=<password>
ME_CONFIG_MONGODB_ADMINUSERNAME=admin
ME_CONFIG_MONGODB_ADMINPASSWORD=<password>

docker compose up -d

This will start the Mongo DB and Mongo Express.


Next I need to edit the server.js connection string to match the credentials, port, and host:

require('dotenv').config();

const DB_HOST = 'server';
const DB_PORT = 27017;
const DB_USERNAME =process.env.DB_USERNAME;
const DB_PASSWORD = process.env.DB_PASSWORD;

const connectionString = `mongodb://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}?authMechanism=DEFAULT`;

Once again, I am using a .env file to keep the username and password secret.

Now I start the server and the client with npm run start.

{{< image src="images/server-db-connection-success.jpg" caption="server connected to database" >}}

It could use some refinement, but it is working as expected.

{{< video src="videos/testing-react-app-2x-speed.mp4" width="100%" >}}

2. Upgrade React-Scripts → Vite

I will upgrade the app font end to use Vite build tools. The app was originally built with Create React App, but this was deprecated in favor of other tools such as Vite, Parcel, and RSBuildVite.

{{< image src="images/create-react-app-deprecation.jpg" caption="Create React App Deprecation blog post" >}}

First I scaffold a new Vite project: npm create vite@latest and select the following options:

  • project Name: client
  • framework: React
  • variant: Typescript

{{< image src="images/vite-scaffold-project.jpg" caption="Scaffold Vite project" >}}

I do some work to hook everything up, then run the dev build.

npm run dev

{{< image src="images/vite-run-dev.jpg" caption="Vite run dev" >}}

It built the site in 121 ms. Very nice.

3. Package Updates

There are a few outdated packages that I should update. I run npm install <package>@latest;

I verify that I do not have any remaining deprecated, old, bad packages:

  • npm audit
  • npm outdated
  • npm ls deprecated

server packages check {{< image src="images/client-package-upgrades.jpg" caption="Client packages check" >}} client packages check {{< image src="images/server-package-upgrades.jpg" caption="Server packages check" >}}

4. Javascript → Typescript Rewrite

The project was sort of a mess anyway, so I will rewrite it in Typescript as I clean it up. The logic and UI handling made the app.js component very fat indeed. I was handling all of the state there, prop-drilling all the way down. It worked, but it did not accord with best practices. Undoubtedly it still does not accord entirely with best practices, if this is even a meaningful concept, but surely I have improved it somewhat anyway. The point was to revive an old project, touch something with React again, and to write some TypeScript, for it is new to me. I liked it.

Anyway, there is nothing very interesting about the process of rewriting to TypeScript. The results are positive. Javascript with types, among other additional features. I extracted some components, restructured the directory, and ended up with a front-end directory like so:

Client / Front-end

└── 📁src
    └── 📁api
        └── api.ts
        └── apiResponse.types.ts
        └── index.ts
    └── 📁components
        └── ColorSelector.jsx
        └── GenericMenu.tsx
        └── Modal.tsx
    └── 📁features
        └── 📁box
            └── box.types.ts
            └── 📁components
                └── BoxCard.tsx
                └── BoxFormModal.tsx
            └── index.ts
            └── 📁services
                └── BoxService.tsx
        └── 📁item
            └── 📁components
                └── ItemCard.tsx
                └── ItemFormModal.tsx
            └── index.ts
            └── item.types.ts
            └── 📁services
                └── ItemService.tsx
    └── 📁icons
        └── Ellipsis.tsx
        └── Garbage.tsx
        └── Icon.tsx
        └── index.ts
        └── Move.tsx
        └── Pencil.tsx
        └── Plus.tsx
        └── Search.tsx
    └── .env
    └── app.tsx
    └── index.css
    └── index.tsx
    └── tsconfig.json
    └── vite-env.d.ts

Server / Back-end

This is a very simple flat directory containing the web API server.

└── 📁server
    └── .env
    └── .gitignore
    └── package-lock.json
    └── package.json
    └── server.js

Database

As I mention above, the MongoDB database is hosted in a Docker container.

└── 📁database
    └── .env
    └── .gitignore
    └── compose.yml

Results

It works. The app source is hosted on my git repository

{{< video src="videos/demo-react-app.mp4" width="100%" >}}