
This project marked the migration of an existing dashboard built with .NET Razor and Vanilla JS on the frontend, to one that uses React and Typescript. The transition aimed to enhance the user experience and leverage the benefits of a modern frontend framework.
Approach
Elements were migrated within the page incrementally, rather than replacing whole pages. This allowed for a more gradual transition where smaller changes could be pushed to production more frequently, reducing the risk of introducing bugs and preventing stale branches.
Components
The dashboard comprises of several components, including:
- Navbar
- Sidebar
- Dropdown menus
- Modals
- Breadcrumbs
- Banners
- Toasts
- Alerts
- Tooltips
- Placeholders / skeletons
Global State Management with Redux
At the start of the migration process, I decided to use React Context to store the global state. As the migration process developed, I soon realised that Redux would be more appropriate for the following purposes - handling a large amount of state, containing complex update logic, and only re-rendering components that depend on the changed state. I swapped out Context for Redux Toolkit, resulting in a much more robust state management solution.
The Redux store comprised of consumables, subscription plan, and user account information.
Unit tests
I used Jest and React Testing Library to create unit tests for all of the new Typescript components. Components that were dependent on global state were tested inside a redux provider, which allows custom test cases for every state.

Handling Forms with React Hook Form
The dashboard includes several different form types. One form functions as a calculator and includes number inputs and radio buttons. Another form is for adding clients and consists of text inputs and an image uploader.
I decided to use React Hook Form in this app for the following reasons: registering each input to a property of the model feels robust, the ‘required’ property options for validation offer great flexibility, and the documentation is easy to understand. The handle submit method only fires when validation passes, so you have confidence that posts to the API are only happening when they should.
Live updates with SignalR
To handle live display updates when consumables are spent, we used SignalR websockets via a Typescript interface. For example, when a credit is spent, the credits hub dispatches a method to update the consumables state in Redux. Every component that makes use of the credits property in Redux is then automatically re-rendered with the new value.
Outcome
The adoption of React with TypeScript has given us a modern codebase that aligns with industry standards and sets the foundation for future enhancements.
Technologies Used:
- React
- Typescript
- Redux Toolkit
- Jest
- React Testing Library
- React Hook Form
- ChartJS
- SignalR
- SCSS