This project is a Phonebook application built with React, Redux Toolkit, and Vite. The main goal of this homework is to practice asynchronous operations, Redux Toolkit with createAsyncThunk, remote backend integration, and state optimization with memoized selectors.
- GitHub Repository: https://github.com/YOUR_USERNAME/goit-react-hw-07
- Live Demo (Vercel): https://YOUR_PROJECT.vercel.app
- React
- Vite
- Redux Toolkit
- createAsyncThunk
- Axios
- Formik & Yup
- CSS Modules
- mockapi.io (REST API backend)
This application allows users to manage a list of contacts. All contacts are stored on a remote backend created with mockapi.io.
Main features include:
- Fetching contacts from a backend API
- Adding new contacts
- Deleting existing contacts
- Filtering contacts by name
- Loading and error handling
- Optimized filtering using memoized selectors
State management is implemented using Redux Toolkit. The global state structure follows the required format:
{
contacts: {
items: [],
loading: false,
error: null
},
filters: {
name: ""
}
}
Redux Persist was completely removed. All data is now fetched from and synchronized with the backend.
All HTTP requests are implemented using createAsyncThunk
and axios inside contactsOps.js.
- fetchContacts — GET /contacts
- addContact — POST /contacts
- deleteContact — DELETE /contacts/:id
Each async operation handles three states:
pending, fulfilled, and rejected,
which are processed inside extraReducers.
After adding loading and error states,
contact filtering could re-run unnecessarily.
To solve this, a memoized selector was implemented using
createSelector.
The selector selectFilteredContacts depends only on:
- The contacts list
- The current name filter
This selector is used directly inside ContactList.jsx
with useSelector.
src/ ├── assets/ │ ├── react.svg │ └── react 2.svg ├── components/ │ ├── Contact/ │ │ ├── Contact.jsx │ │ └── Contact.module.css │ ├── ContactForm/ │ │ ├── ContactForm.jsx │ │ └── ContactForm.module.css │ ├── ContactList/ │ │ ├── ContactList.jsx │ │ └── ContactList.module.css │ └── SearchBox/ ├── redux/ │ ├── contactsOps.js │ ├── contactsSlice.js │ ├── filtersSlice.js │ ├── store.js ├── App.jsx ├── App.css ├── index.css └── main.jsx
When the application loads, contacts are fetched from the backend
inside the App component using useEffect
and dispatch(fetchContacts()).
The application runs without console errors or warnings and fully satisfies all homework requirements.
This homework focuses on real-world Redux patterns, clean async logic, backend communication, and performance optimization using memoized selectors.
Happy coding! 🚀