+++ categories = ["software"] tags = ["react","typescript","javascript"] date = 2025-04-12T00:00:00-06:00 description = "" draft = false slug = "react-app-resurrection" title = "⚛️ React App Resurrection" author = "nicholas" +++ [Project git repo](https://git.uuard.com/nicholas/storage-manager) 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: - **M**ongoDB (Database) - **E**xpress.js (Backend framework) - **R**eact (Frontend framework) - **N**ode.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** ```yaml 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** ```env MONGO_INITDB_ROOT_USERNAME=root MONGO_INITDB_ROOT_PASSWORD= ME_CONFIG_MONGODB_ADMINUSERNAME=admin ME_CONFIG_MONGODB_ADMINPASSWORD= ``` `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: ```javascript 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 @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](https://git.uuard.com/nicholas/storage-manager) {{< video src="videos/demo-react-app.mp4" width="100%" >}}