## TASK 1: React project setup. Class components. Error boundary.
Link: https://github.com/rolling-scopes-school/tasks/blob/master/react/modules/tasks/class-components.md
This project is a React application built using Vite, TypeScript, and modern development tools like ESLint, Prettier, and Husky. It follows best practices for code quality, formatting, and Git hooks.
- React with TypeScript: Type-safe React components.
- Vite: Fast development server and build tool.
- ESLint: Static code analysis for catching errors and enforcing coding standards.
- Prettier: Automated code formatting for consistent style.
- Husky: Git hooks for running linting and formatting before commits.
- Error Boundary: Graceful error handling with a fallback UI.
- Local Storage Integration: Persists search terms across sessions.
- API Integration: Fetches data from a RESTful API (e.g., PokeAPI, SWAPI).
- Setup Node.js
- Install vite & run NPM install
npm create vite@latest rs-react-app -- --template react-ts
cd rs-react-app
npm install
npm run dev- Set up ESLint and Prettier
npm install -D eslint-plugin-react eslint-plugin-prettier eslint-config-prettier eslint-plugin-react-compiler@beta
npm install -D --save-exact prettierAdd a new file .prettierrc to the root of the project:
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": true
}Update file eslint.config.js
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import react from 'eslint-plugin-react';
import tseslint from 'typescript-eslint';
import eslintPluginPrettier from 'eslint-plugin-prettier/recommended';
import reactCompiler from 'eslint-plugin-react-compiler';
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [
js.configs.recommended,
...tseslint.configs.strict,
eslintPluginPrettier,
],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
'react-compiler': reactCompiler,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
'react-compiler/react-compiler': 'error',
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
},
settings: {
react: {
version: 'detect',
},
},
}
);- Husky Setup
npm install --save-dev husky
npx husky init
npx husky add .husky/pre-commit "npm run lint"- Add package.json commands:
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext ts,tsx --fix",
"format:fix": "prettier --write .",
"prepare": "husky install"/
├── src/
│ ├── components/
│ │ ├── Search.tsx
│ │ ├── CardList.tsx
│ │ ├── Card.tsx
│ │ └── ErrorBoundary.tsx
│ ├── App.tsx
│ └── main.tsx
├── .eslintrc.js
├── .prettierrc
├── package.json
├── tsconfig.json
├── README.md
└── .gitignore
Successful response.
+-------------------------------------------------------+
| |
| +------------------ Top controls ------------------+ |
| | +--------------------------+ +-----------------+ | |
| | | [Search Input Field] | | [Search Button] | | |
| | +--------------------------+ +-----------------+ | |
| +--------------------------------------------------+ |
| |
| +-------------------- Results ---------------------+ |
| | +----------------------------------------------+ | |
| | | Item Name | Item Description | | |
| | +----------------------------------------------+ | |
| | | [Item 1] | [Description 1] | | |
| | | [Item 2] | [Description 2] | | |
| | | ... | ... | | |
| +--------------------------------------------------+ |
| [Error Button] |
+-------------------------------------------------------+
Non-successful response.
+-------------------------------------------------------+
| |
| +------------------ Top controls ------------------+ |
| | +--------------------------+ +-----------------+ | |
| | | [Search Input Field] | | [Search Button] | | |
| | +--------------------------+ +-----------------+ | |
| +--------------------------------------------------+ |
| |
| +-------------------- Results ---------------------+ |
| | | |
| | Error description | |
| | | |
| +--------------------------------------------------+ |
| [Error Button] |
+-------------------------------------------------------+
## TASK 2: React Routing. Tests.
Link: https://github.com/rolling-scopes-school/tasks/blob/master/react/modules/tasks/routing.md
- Converted all class components into functional components except the Error Boundary component.
- Created a custom hook to restore the search query from local storage.
- Used appropriate React lifecycle hooks.
- Ensured state management was handled within individual components.
- Implemented routing using React Router in SPA (non-SSR) mode.
- Added a 404 page for non-existing routes.
- Implemented pagination for the existing item list (search results).
- Updated the browser URL with the current page using query parameters.
- Ensured the pagination component appears after receiving the full list of items.
- Configured the main page to display search results.
- On item click, the page was split into two sections:
- The left section continued to display search results.
- The right section displayed item details using Router Outlet.
- Added a loading indicator while fetching additional details.
- Implemented a close button for the details section.
- Allowed closing the details section by clicking on the left section.
- Reflected the state of the opened details section in the URL (e.g., /?frontpage=2&details=1).
- Configured Jest as the test runner.
- Ensured the test runner displayed test coverage.
- Achieved at least 70% test coverage (excluding App.tsx).
- Included only .tsx files in coverage.
- Integrated React Testing Library for component testing.
To set up routing, the following library was installed:
npm install react-router-domThe following packages were installed for testing:
npm install --save-dev jest @testing-library/react @testing-library/jest-dom ts-jest jest-environment-jsdom identity-obj-proxyAll changes were implemented in a dedicated branch:
git checkout -b hooks-and-routing## TASK 3: Redux. Redux Toolkit, RTK Query. Context api.
Link: https://github.com/rolling-scopes-school/tasks/blob/master/react/modules/tasks/redux.md
To implement a custom theme selection feature, the following changes were made:
- Created
ThemeProviderandThemeContextto manage the application's theme. - Added a theme selection option theme button to allow users to switch between light and dark themes.
- Ensured the selected theme applies to the entire application by wrapping the app with
ThemeProvider.
To support dynamic theming, Redux state management, and API requests, the following libraries were installed:
npm install classnames
npm install @reduxjs/toolkit axios react-reduxclassnames– Used for conditionally applying CSS class names based on the selected theme.@reduxjs/toolkit– Integrated Redux into the application, including setting up the store and reducers.axios– Used for making API requests to fetch data.react-redux– Provided React bindings for Redux to connect components with the store.
To implement item selection and management using Redux, the following changes were made:
- Each item in the dashboard now has a checkbox to allow selection.
- Selected items are stored in the Redux store, ensuring persistence across page navigations.
- Unselecting an item removes it from the store dynamically.
- A flyout panel appears when at least one item is selected, displaying the total number of selected items and providing two actions:
- "Unselect all" – Clears all selections and hides the flyout.
- "Download" – Exports the list of selected items to a
.csvfile.
RTK Query was implemented to optimize API interactions:
- Replaced direct API calls with RTK Query, improving caching and reducing redundant requests.
- Implemented a loading state in the store, ensuring smooth UI updates without prop-drilling.
- Stored API responses in Redux, maintaining the current page’s data.
All changes were implemented in a dedicated branch:
git checkout -b app-state-management