forked from yugank-rai/React.js_notes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathL10(React-Redux).js
More file actions
190 lines (150 loc) · 5.97 KB
/
L10(React-Redux).js
File metadata and controls
190 lines (150 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* -----------------------------------------------------------------------------
TOPIC: React Redux (with Redux Toolkit)
SOURCE: Piyush Garg (React Tutorial Series)
DESCRIPTION:
As apps grow, passing data (props) from parent -> child -> grandchild
becomes messy. This is called "Prop Drilling".
Redux solves this by creating a Central "Store" (like a database in the frontend)
that any component can access directly, regardless of where it is in the tree.
KEY TERMS:
1. Store: The single place where all application state lives.
2. Slice: A chunk of the store handling a specific feature (e.g., CartSlice, UserSlice).
3. Action: Describes "what happened" (e.g., "ADD_TO_CART").
4. Reducer: A function that says "how the state changes" based on the action.
5. Dispatch: How we send an action to the store.
6. Selector: How we get data out of the store.
-----------------------------------------------------------------------------
*/
// ==========================================
// 0. INSTALLATION
// ==========================================
// npm install @reduxjs/toolkit react-redux
// ==========================================
// 1. CREATING A SLICE (redux/slices/cartSlice.js)
// ==========================================
/* A "Slice" contains the initial state and the functions (reducers)
to modify that state. Redux Toolkit's `createSlice` makes this very easy.
*/
import { createSlice } from "@reduxjs/toolkit";
const cartSlice = createSlice({
name: "Cart",
initialState: [], // Initial state is an empty array (empty cart)
// Reducers: Functions that define HOW to change the state
reducers: {
// Function to add an item to the cart
addItem: (state, action) => {
// In older Redux, we had to return a NEW array (immutability).
// In Redux Toolkit, we can "mutate" state directly (it handles immutability behind the scenes).
state.push(action.payload);
},
// Function to remove an item (logic can be added here)
removeItem: (state, action) => {
// logic to remove item
}
}
});
// Export the "Actions" so components can use them
// createSlice automatically generates actions with the same names as reducers
export const { addItem, removeItem } = cartSlice.actions;
// Export the "Reducer" so the Store can use it
export default cartSlice.reducer;
// ==========================================
// 2. CONFIGURING THE STORE (redux/store.js)
// ==========================================
/*
The Store is the global container combining all your slices.
*/
import { configureStore } from "@reduxjs/toolkit";
import cartReducer from "./slices/cartSlice"; // Import the reducer we just made
export const store = configureStore({
reducer: {
cart: cartReducer, // We name this slice 'cart'
// user: userReducer, // We could add more slices here
},
});
// ==========================================
// 3. PROVIDING THE STORE (main.jsx / index.js)
// ==========================================
/*
We need to wrap our entire React app in the <Provider>
so that every component can access the Redux Store.
*/
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import { Provider } from "react-redux"; // Import Provider
import { store } from "./redux/store"; // Import the store we created
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
{/* Pass the store to the Provider */}
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// ==========================================
// 4. WRITING DATA: DISPATCH (Product.jsx)
// ==========================================
/*
To change the state (e.g., Add item to cart), we "Dispatch" an action.
Hook: useDispatch()
*/
import React from "react";
import { useDispatch } from "react-redux";
import { addItem } from "../redux/slices/cartSlice"; // Import the action
const Product = ({ name, price }) => {
const dispatch = useDispatch(); // Initialize the hook
const handleAddToCart = () => {
// dispatch(actionName(data))
// 'data' here becomes 'action.payload' in the slice
dispatch(addItem({ name: name, price: price }));
};
return (
<div className="card">
<h3>{name}</h3>
<p>${price}</p>
<button onClick={handleAddToCart}>Add to Cart</button>
</div>
);
};
export default Product;
// ==========================================
// 5. READING DATA: SELECTOR (Cart.jsx)
// ==========================================
/*
To read data from the store, we use a "Selector".
Hook: useSelector()
*/
import React from "react";
import { useSelector } from "react-redux";
const Cart = () => {
// useSelector takes the entire global state and returns just what we need
// state.cart matches the key we defined in store.js
const items = useSelector((state) => state.cart);
// Calculate total price
const total = items.reduce((a, b) => a + b.price, 0);
return (
<div className="alert alert-success">
<h3>Total Items: {items.length}</h3>
<h3>Total Bill: ${total}</h3>
{/* Displaying items */}
<ul>
{items.map((item, index) => (
<li key={index}>{item.name} - ${item.price}</li>
))}
</ul>
</div>
);
};
export default Cart;
// ==========================================
// 6. SUMMARY: THE DATA FLOW
// ==========================================
/*
1. User clicks "Add to Cart" Button.
2. Component calls dispatch(addItem({name: 'Macbook'})).
3. Action travels to the Store's Reducer.
4. Reducer (in cartSlice) receives the action and pushes payload to state.
5. Store updates the state.
6. Any component using useSelector (like Cart.jsx) detects the change and re-renders automatically with new data.
*/