This project was bootstrapped with Create React App, using the Redux and Redux Toolkit template.
This app pairs well with this node-js express template
- Available Scripts
- Learn More
- Features
- Environment Variables
- Folder Structure
- Authentication
- User Management
- Pagination
- Animation
- Linting
- License
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.
- Static Typing: TypeScript static typing using typescript
- Testing: unit and integration tests using Jest
- State Management: Redux Toolkit state management with redux using redux toolkit
- Cache Handling: RTK Query Cache management using rtk query
- Notifications: react-toastify awesome toast notifications with react-toastify
- Styling: React Bootstrap style with bootstrap components via React Bootstrap
- SASS: SASS style more with SASS
- Animations: React Transition Group animate using an Animate component created using elements from React Transition Group
- Pagination: React Bootstrap Pagination paginate with custom component built on React Bootstrap's Pagination
- Error handling: RTK Query Error Handling centralized error handling mechanism for fetch requests using rtk query middleware
- CI: continuous integration with GitHub CI
- Code coverage: using codecov
- Git hooks: with husky and lint-staged
- Linting: with ESLint and Prettier
- Changelog Generation: with Standard Version
- Structured Commit Messages: with Commitizen
- Commit Linting: with CommitLint
Create your environment variables by copying the .env.example
file i.e.
cp .env.example .env.local
src
├── app # Redux configuration
│ ├── api.ts # base redux API
│ ├── hooks.ts # redux hooks
│ ├── middleware.ts # redux middleware
│ └── store.ts # redux store
├── assets # assets
│ └── img
├── custom.d.ts # extended custom types
├── index.tsx # app entry
├── __mocks__ # test utils and mocks
│ ├── data.ts
│ ├── server.ts
│ └── utils.tsx
├── modules # app modules including pages, components and APIs
│ ├── auth # pages, components, tests, and redux API for auth
│ ├── common # common components and tests. includes Routing
│ ├── dashboard # dashboard pages, components, and tests
│ ├── pages # pages
│ └── users # pages, components, tests, and redux API for users
├── react-app-env.d.ts
├── serviceWorker.ts
├── setupTests.ts
├── styles # styling
│ ├── components # component styling e.g. loader
│ ├── _components.scss # imports
│ ├── custom.scss # root styling file
│ ├── layout # layout components
│ ├── _layouts.scss # imports
│ ├── mixins # mixins
│ ├── _mixins.scss # imports
│ ├── utilities # utilities like transform styles
│ ├── _utilities.scss # imports
│ └── _variables.scss # custom variables
Authentication has already been done for you with the redux-toolkit query API setup. The app was created with APIs from this node-template in mind.
Pages included in the app include:
- Login
- Register
- Forgot Password
- Reset Password
- Verify Email
Like authentication, user management has already been done for you using rtk query.
Wrapper for pages that require authentication. Just wrap the route element with RequireAuth and only logged in users with permissions will have access.
import { Routes, Route } from 'react-router-dom';
import RequireAuth from './RequireAuth';
import { DashboardHome, Profile } from '../../dashboard';
import restrictions from './restrictions';
import routes from './routes';
const MainRouter = () => {
return (
<Routes>
<Route path={routes.Dashboard.absolutePath}>
{/* dashboard will be restricted to all logged in users */}
<Route index element={<RequireAuth element={<DashboardHome />} restrictedTo={restrictions.none} />} />
{/* profile will be restricted to logged in admin users */}
<Route
path={routes.Profile.relativePath}
element={<RequireAuth element={<Profile />} restrictedTo={restrictions.admin} />}
/>
</Route>
</Routes>
);
}
As an added bonus: all the navigation items in the dashboard sidebar are also authenticated before being displayed. Define nav items with restrictions e.g.
{/* They are automatically restricted to all logged in users*/}
<NavItem
title="List"
link={routes.UserList.absolutePath}
pathname={location.pathname}
icon={faList}
restrictedTo={restrictions.admin}
/>
Pagination is done using custom logic built on top of React Bootstrap's Pagination component.
Just wrap your component like so
import React, { useState } from 'react';
const [currentPage, setCurrentPage] = useState<number>(1);
const data = fetchSomeData({ page: currentPage });
const onPageClick = (page: number) => {
setCurrentPage(page);
};
<Paginate currentPage={currentPage} onPageClick={onPageClick} totalPages={data.totalPages}>
{data.map((item) => (
<h1 key={item.id}>{item.name}</h1>
))}
</Paginate>
Animate your component using custom css styles and a component built using React Transition Group. Animating is as easy as:
import Animate from 'blob/components/Animate';
const customComponent = () => {
return (
<>
<Animate>
<h1>This text will animate</h1>
</Animate>
</>
);
};
You can change animation behavior by defining css classes and adding them to the Animate component
Linting is done using ESLint and Prettier.
In this app, ESLint is configured to follow the Airbnb JavaScript style guide with some modifications. It also extends eslint-config-prettier to turn off all rules that are unnecessary or might conflict with Prettier.
To modify the ESLint configuration, update the .eslintrc.json
file. To modify the Prettier configuration, update the prettier configuration in package.json
.
To prevent a certain file or directory from being linted, add it to .prettierignore
.