A step-by-step demo of scaffolding an app using create-react-app + TypeScript + Material UI
Then only dependency is to install the latest LTS version of NodeJS
There is a branch for each step showing the completed step state. Master reflects the final step state. You can jump between branches to view the completed step or compare branches to see the difference.
Generate a scaffolded app using the single create-react-app command using the TypeScript template:
npx create-react-app my-app --template typescript
Add VS Code launch and attach debug configurations
Following the steps here we add the:
- Material UI library
- Roboto Font
- Font Icons
- SVG Icons
Follow the minimizing bundle size guide. This is an optimisation but is nice to do upfront as standard.
We add:
- babel-plugin-transform-imports
- react-app-rewired
- customize-cra
- some babel config
- a function in
customize-cra
to apply the babel config
Now we are about to write some code:
- add .editorconfig and .prettierrc
- turn on auto format on save (no manual formatting or disagreements required)
- delete the OOTB CRA styling and HTML
- follow the Usage page
- add the responsive meta tag
- add CssBaseline
- create and apply the dark theme
- use MUI Typography
We will start off making the layout more 'mobile first' with a container + maxWidth and menu bar:
- add a responsive Container
- create a component called MenuBar
- add some styles to the MenuBar component
We will install react-router-dom and add:
- a 'landing' page for the default route '/'
- a 'survey' page for 'survey'
- a button on each one to navigate between
We will start off basic:
- npm install axios axios-hooks
- use the useAxios hook to call https://icanhazdadjoke.com/ random joke API
- display the text
- hook up a button to use the refetch function and loading state
Also add some more DX stuff:
- create a list of recommended extensions (eslint, prettier, editorconfig support)
- local settings to tell VS code to use prettier-vscode extension for formatting
- No one likes hard coded endpoint addresses, set up a .env file with config
- It's nice to be able to see an indication of network calls in progress, lets add support for app-level network status through axios interceptors
- Create a hook that supports communication from non-react code (axios) to React code via useEffect (and useState)
- Create a NetworkErrorAlert component to show network failures as error messages
- Consider the complexity of this code and alternatives
- Consider alternatives for where to embed 'behaviour' such as asynchronous IO (in presentation components, container components or outside components, e.g. in Redux action creators that can be use anywhere)
- Create 3 survey page components to display (Page1, Page2, Page3)
- Add nested routing under /survey to navigate between the page components
- Add some MUI input components to each page
-
Maintain state within each component and use a callback to notify the main survey component when each section is complete
-
Consider the amount of boilerplate for 'controlled components'
-
Consider the amount of code to write validation manually
-
Look at some form validation libraries
- Add the recoil library
- Create recoil
atom
s to hold each page's data - Create a recoil
selector
to represent the combined data across all pages - Refactor the parent component to
useRecoilState
- Recoil supports simple subscription to state changes (remove NetworkStateNotifier)
- Set up atoms to store the number of active requests and the last network error
- Call recoil
SetterOrUpdater<T>
from axios interceptors viaNetworkStatusProvider
, a simple component to calluseSetRecoilState
from React code and obtain theSetterOrUpdater<T>
. - Export hooks to allow consumers to
useNetworkIsActive
anduseNetworkLastError
without access to the actual recoil state. - Use a recoil async selector to preload a dad joke from the landing page and display the result in each survey form page (demonstrates server state caching and preloading).
This project was bootstrapped with Create React App.
In the project directory, you can run:
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
Note: this is a one-way operation. Once you eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.