https://github.com/ch0ripain/react-context-and-reducer
🔷 Simple React - Context & Reducer - Project 🔷
https://github.com/ch0ripain/react-context-and-reducer
frontend react react-context react-context-api react-reducer react-reducer-provider reactjs web-development
Last synced: 9 months ago
JSON representation
🔷 Simple React - Context & Reducer - Project 🔷
- Host: GitHub
- URL: https://github.com/ch0ripain/react-context-and-reducer
- Owner: ch0ripain
- Created: 2024-11-19T21:25:16.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-11-28T01:11:31.000Z (about 1 year ago)
- Last Synced: 2025-02-14T15:47:06.370Z (10 months ago)
- Topics: frontend, react, react-context, react-context-api, react-reducer, react-reducer-provider, reactjs, web-development
- Language: JavaScript
- Homepage: https://react-context-and-reducer.vercel.app
- Size: 1.11 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
🚀 Quick Introduction to React Context & Reducer 🚀
## 🌐 Context 🌐
In React, a Context is a common way to share state globally across your application.
To get started, you first need to create the context. This can be done using a function provided by React ➡️ createContext
```javascript
import { createContext } from "react";
export const CartContext = createContext({
items: [],
addItemToCart: () => {},
updateCartItemQuantity: () => {},
});
```
As shown above, we need to import createContext to make it available for use.
The createContext function can accept any JavaScript expression, such as [], {}, 5, or 'context'
In this example, we define an object with some properties initialized to undefined values. This is a common best practice as it allows us to clearly define the properties of our context while enabling code autocompletion in our editor.
A standard approach to make the context usable is to wrap it in a component using the Context.Provider property.
```javascript
export default function CartContextProvider({ children }) {
const contextValue = {
items: shoppingCartState.items,
addItemToCart: handleAddItemToCart,
updateCartItemQuantity: handleUpdateCartItemQuantity,
};
return (
{children}
);
}
```
Finally, we need to wrap our main component with the context provider. This ensures that the main component and all its child components will have access to the context.
```javascript
import CartContextProvider from "./store/shopping-cart-context.jsx";
function App() {
return (
{DUMMY_PRODUCTS.map((product) => (
))}
);
}
```
## 🌀 Reducer 🌀
```javascript
const [shoppingCartState, shoppingCartDispatch] = useReducer(
shoppingCartReducer,
{
items: [],
}
);
//...
{items.length == 0 && No items :(}
//...
```
As shown above, the
shoppingCartState should be treated as a read-only value.
On the other hand, shoppingCartDispatch is the dispatcher function that we use to pass the updated state and the type of change we want to perform.
The useReducer() hook takes two arguments:
- A function that contains all the logic for updating the state.
- The initial state value.
In essence, useReducer is a hook similar to useState, but all state updates are managed in a separate function, providing a more structured way to handle complex state logic.
```javascript
function shoppingCartReducer(state, action) {
if (action.type === "ADD_ITEM") {
const updatedItems = [...state.items];
const existingCartItemIndex = updatedItems.findIndex(
(cartItem) => cartItem.id === action.payload.id
);
//...
}
}
```
shoppingCartReducer function takes two parameters:
- state ➡️ the most recent state when the reducer function is called.
- action ➡️ typically an object containing key-value pairs, such as {type: 'ADD_ITEM', payload: id}
## 🌐 Using context 🌐
To use a context, we need to import two things:
```javascript
import { useContext } from "react";
import { CartContext } from "../store/shopping-cart-context";
```
Next, we can destructure the specific context we need from the context object we previously created.
```javascript
const { items, updateCartItemQuantity } = useContext(CartContext);
```
Finally, we use the context as intended in our application.
```javascript
const totalPrice = items.reduce(
(acc, item) => acc + item.price * item.quantity,
0
);
```
```javascript
{items.map((item) => {
//...
updateCartItemQuantity(item.id, -1)}>
//...
}
```
> [!NOTE]
> Prop drilling is passing data through multiple layers of components via props. Context avoids this by providing a way to share data directly with any component, no matter how deep it is in the tree.
With all the above, we have implemented a global state using context, avoiding prop drilling and separating the state update logic using a reducer.
This approach makes our code cleaner, more maintainable, and easier to understand.
---
🐸 This project is a practice exercise I learned from the Academind's React Course 🐸