I wrote this Tennis score keeper app about 5 years ago in React and Redux and decided to give it a refresh.
There were a few issues with my existing project:
- I used create-react-app for the front end tooling and it is now deprecated.
- Node-sass is deprecated and the project gives an error when starting.
- The API for Redux had changed.
My goal for the refresh was to remove the dependency for Sass and Redux. I don’t mind using them but don’t think they are necessary for this project.
Create-react-app alternative
The recommended alternative is Vite so I installed it and created a new project.
Migrating old code
Rather than upgrading the existing project, in this case it was simpler to just copy code across to the new project. Next, Sass and all CSS styles were removed. Then, all Redux reducers (and their calls) were commented out. Also I updated React Router. This enabled the project to run without errors.
Instead of Redux, I wanted to just use the Context API which is built into React. Theres a nice guide here on how to use it to manage state.
I converted MenuReducer
first as its the smallest reducer.
This is what looked like before with Redux:
// menuReducer.js export const initialState = { selected: false } export default function menuReducer(state = initialState, action) { switch (action.type) { case 'TOGGLE_MENU': return { ...state, selected: action.payload } default: return state } }
This is afterwards with the Context API:
//menuContext.js import { createContext, useContext, useState } from "react"; import PropTypes from "prop-types"; export const initialState = { selected: false } const MenuContext = createContext(null); const MenuProvider = ({ children }) => { const [menu, setMenu] = useState(initialState); const toggleMenu = () => { setMenu((menu) => ({ ...menu, selected: !menu.selected })); }; const value = { menu, toggleMenu }; return <MenuContext.Provider value={value}>{children}</MenuContext.Provider>; }; MenuProvider.propTypes = { children: PropTypes.node.isRequired, }; const useMenu = () => { const value = useContext(MenuContext); if (!value) { throw new Error("Error: Hook used without MenuContext."); } return value; }; export { MenuProvider, MenuContext, useMenu };
The state is saved in the Provider, then the individual functions that handle the state are exported. This maintains the same pattern as before, except instead of dispatching actions, the exported function can be invoked from any component that utilizes the context.
There is more code here than before, but I’m ok with this as Redux has been removed. Also the hook to use the context is included in the new code.
Once I got this reducer converted, the pattern was just replicated to the other reducers.
BeerCSS

After the app was working again, I thought about what to do about the UI. I knew that I wanted a Material style look but using the MUI framework is overkill for a small project like this.
I found BeerCSS which is a tiny library for styling apps. It can even be installed simply by using a CDN:
<link href="https://cdn.jsdelivr.net/npm/beercss@3.9.7/dist/cdn/beer.min.css" rel="stylesheet"> <script type="module" src="https://cdn.jsdelivr.net/npm/beercss@3.9.7/dist/cdn/beer.min.js"></script>

After some fiddling with the markup, this is what the final result looks like🎉