React TypeScript - Build eCommerce Project (Redux, TanStack)
React TypeScript - Build eCommerce Project (Redux, TanStack)
Building an eCommerce project using React and TypeScript is an excellent way to level up your front-end skills.
Buy Now
Incorporating advanced tools like Redux for state management and TanStack (formerly known as React Query) for efficient server data handling brings modern development practices into the mix. In this guide, we’ll walk through how to set up a React TypeScript eCommerce project using these technologies.
Project Setup
Initializing the Project
Begin by setting up your project with Create React App, which provides a boilerplate React environment with TypeScript support.
bashnpx create-react-app ecommerce-ts --template typescript
This command will create a new React project with TypeScript configured. You can verify it by checking the file extensions (
.tsx
for React components and.ts
for regular TypeScript files).Installing Dependencies
Once the project is set up, you need to install essential dependencies for managing state and handling server-side interactions. For this project, we’ll use Redux Toolkit, TanStack Query, and a few other libraries.
bashnpm install @reduxjs/toolkit react-redux @tanstack/react-query axios react-router-dom
- Redux Toolkit simplifies setting up Redux for state management.
- TanStack Query is a library for handling server-side state efficiently, enabling features like caching, background updates, and more.
- Axios is used for making HTTP requests.
- React Router helps manage navigation in the application.
Building the Store with Redux
Setting Up Redux Toolkit
Redux helps manage global state, which is crucial for handling eCommerce data like products, cart, and user details.
Create a folder structure for your Redux logic:
csssrc/ ├── app/ │ └── store.ts └── features/ ├── products/ ├── cart/ └── user/
Inside
store.ts
, initialize the Redux store:typescriptimport { configureStore } from '@reduxjs/toolkit'; import productsReducer from '../features/products/productsSlice'; import cartReducer from '../features/cart/cartSlice'; import userReducer from '../features/user/userSlice'; export const store = configureStore({ reducer: { products: productsReducer, cart: cartReducer, user: userReducer, }, }); export type RootState = ReturnType<typeof store.getState>; export type AppDispatch = typeof store.dispatch;
Here, we create a store that combines three slices:
products
,cart
, anduser
.Creating the Products Slice
The
productsSlice
handles the logic related to fetching and storing products in the state.typescriptimport { createSlice, PayloadAction } from '@reduxjs/toolkit'; interface Product { id: number; name: string; price: number; description: string; image: string; } interface ProductsState { items: Product[]; status: 'idle' | 'loading' | 'succeeded' | 'failed'; } const initialState: ProductsState = { items: [], status: 'idle', }; const productsSlice = createSlice({ name: 'products', initialState, reducers: { setProducts(state, action: PayloadAction<Product[]>) { state.items = action.payload; }, }, }); export const { setProducts } = productsSlice.actions; export default productsSlice.reducer;
This slice includes a state for storing products and a reducer function to update the state with fetched products.
Fetching Data with TanStack Query
Using TanStack Query for Server Data
TanStack Query simplifies data fetching and caching in React applications. Here, we’ll use it to fetch the products from a mock API.
Create a
useProducts.ts
hook:typescriptimport { useQuery } from '@tanstack/react-query'; import axios from 'axios'; import { Product } from '../features/products/productsSlice'; const fetchProducts = async (): Promise<Product[]> => { const { data } = await axios.get('/api/products'); return data; }; export const useProducts = () => { return useQuery(['products'], fetchProducts); };
This hook uses
useQuery
to fetch products. The hook handles loading, error, and caching states automatically.Displaying Products in the Component
In the
ProductsList.tsx
component, you can use theuseProducts
hook to fetch and display products.typescriptimport React from 'react'; import { useProducts } from '../hooks/useProducts'; import { useAppDispatch } from '../app/hooks'; import { setProducts } from '../features/products/productsSlice'; const ProductsList: React.FC = () => { const { data, error, isLoading } = useProducts(); const dispatch = useAppDispatch(); React.useEffect(() => { if (data) { dispatch(setProducts(data)); } }, [data, dispatch]); if (isLoading) return <p>Loading...</p>; if (error) return <p>Error loading products</p>; return ( <div> {data?.map((product) => ( <div key={product.id}> <h3>{product.name}</h3> <p>{product.description}</p> <p>${product.price}</p> </div> ))} </div> ); }; export default ProductsList;
Here, we fetch the products using
useProducts
and store them in the Redux store withsetProducts
. TheuseEffect
hook is triggered when the products data is available.
Managing Cart with Redux
Creating the Cart Slice
The
cartSlice
manages the cart state, allowing users to add and remove items from their shopping cart.typescriptimport { createSlice, PayloadAction } from '@reduxjs/toolkit'; interface CartItem { id: number; quantity: number; } interface CartState { items: CartItem[]; } const initialState: CartState = { items: [], }; const cartSlice = createSlice({ name: 'cart', initialState, reducers: { addToCart(state, action: PayloadAction<number>) { const item = state.items.find((item) => item.id === action.payload); if (item) { item.quantity++; } else { state.items.push({ id: action.payload, quantity: 1 }); } }, removeFromCart(state, action: PayloadAction<number>) { state.items = state.items.filter((item) => item.id !== action.payload); }, }, }); export const { addToCart, removeFromCart } = cartSlice.actions; export default cartSlice.reducer;
This slice contains actions to add items to the cart or remove them. The cart state is stored as an array of
CartItem
objects, each containing the product ID and quantity.Connecting the Cart to the UI
Now, in the
ProductDetails.tsx
component, you can use theaddToCart
action to allow users to add products to their cart.typescriptimport React from 'react'; import { useAppDispatch } from '../app/hooks'; import { addToCart } from '../features/cart/cartSlice'; interface ProductDetailsProps { id: number; name: string; price: number; } const ProductDetails: React.FC<ProductDetailsProps> = ({ id, name, price }) => { const dispatch = useAppDispatch(); const handleAddToCart = () => { dispatch(addToCart(id)); }; return ( <div> <h2>{name}</h2> <p>${price}</p> <button onClick={handleAddToCart}>Add to Cart</button> </div> ); }; export default ProductDetails;
This component allows the user to add products to the cart, dispatching the
addToCart
action when the button is clicked.
Final Touches
Routing with React Router
Use React Router to manage navigation between different pages, such as the product list, product details, and cart page.
typescriptimport { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; import ProductsList from './components/ProductsList'; import Cart from './components/Cart'; function App() { return ( <Router> <Routes> <Route path="/" element={<ProductsList />} /> <Route path="/cart" element={<Cart />} /> </Routes> </Router> ); } export default App;
This sets up basic routing, with a home route displaying the product list and a
/cart
route showing the cart.
React JS Course
Conclusion
With Redux for state management and TanStack Query for server-side data fetching, you have a powerful architecture for building a scalable eCommerce application. By combining these tools in a React TypeScript project, you can effectively manage global state, handle caching and background updates, and provide a seamless user experience.
Post a Comment for "React TypeScript - Build eCommerce Project (Redux, TanStack)"