Let’s initialize Redux (the toolkit) in React in a fast way. (JavaScript) ⚡⚡⚡
This is not suitable for people who think “React” is the word that means to respond or behave in a particular way in response to something.
I want to write the medium for people who want to use Redux in React right now. Especially me, who wants to use Redux instead of useContext for state management.
Edit: This method is used for Javascript because I try to use it in React TypeScript. It doesn’t work. 😢
Let’s Kick off. 💨
1- Install Redux
npm install @reduxjs/toolkit react-redux
2- Create a Redux Store
Create a file named src/store/index.js
and put this code.
// src/store/index.js
import { configureStore } from '@reduxjs/toolkit'
export default configureStore({
reducer: {},
})
3- Add Provider to your App
Update index.js in your root directory.
// src/index.js
// ... Other imports
// First: imports store and Provider
import store from './app/store'
import { Provider } from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'))
// Add Provider from `react-redux`
root.render(
<Provider store={store}>
<App />
</Provider>
)
4- Create Reducer
Create a file named src/store/reducers/counter.js
.
This is just initial code for you; If you want to write your own actions (see full example in 4.1)
createSlice: A function that combines the action creators and reducers into a single concise syntax for defining slices of the store state.
// src/store/reducers/counter.js
import { createSlice } from '@reduxjs/toolkit'
// set initial state
const initialState = {
};
export const anySlice = createSlice({
name: 'any',
initialState: initialState,
reducers: {
},
})
export const { } = anySlice.actions
export default anySlice.reducer
4.1- Add Action for the reducer object
// src/store/reducers/counter.js
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
value: 0,
};
export const counterSlice = createSlice({
name: 'counter',
initialState: initialState,
// Add Actions as you want
reducers: {
increment: (state) => {
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})
// Add this line for using those action
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
5- Add Slice Reducers to the Store
Update reducer object in src/store/index.js
// src/store/index.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './reducers/counter'
export default configureStore({
reducer: {
counter: counterReducer, // <------- Add this
},
})
6- use The redux
Go to your component.
// src/components/Counter.js
// ...Other imports
// ---------------------------First---------------------------
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from '../store/reducers/counter.js'
export function Counter() {
// --------------------------- Second ---------------------------
// Get the "value" value form couter by using useSelector
const {value}= useSelector((state) => state.counter)
// --------------------------- Third ---------------------------
// dispatch can use to call any actions in reducers
const dispatch = useDispatch()
// Example : dispatch(increment()) is used for call increment function
// in couter reducer
// : dispatch(incrementByAmount(10)) if you want to send a payload.
// there's going to be action.payload in the reducer
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
<button
aria-label="Increment By 10"
onClick={() => dispatch(incrementByAmount(10))}
>
Increment By 10
</button>
</div>
</div>
)
}
In conclution
This is all for today. I know this might be rough for someone who met Redux for the first time. But I hope you guys understand some of the basics of Redux or how to use it. :D
Bonus ( Do you want more example ? Yesss)
This is my code that I changed from using useContext to Redux.
Redux
// src/utils/store/reducers/cart.js
import { createSlice } from "@reduxjs/toolkit";
// Set initial state
const initialState = {
items: [],
};
// Create a new slice of the Redux store named "cart"
export const cartSlice = createSlice({
name: "cart",
initialState: initialState,
reducers: {
// Reducer function: "addToCart"
addToCart: (state, action) => {
const product = action.payload;
// Check if the product already exists in the cart by comparing its name
const existedProduct = state.items.some(
(item) => item.name === product.name
);
if (existedProduct) {
// If the product exists, update its quantity in the cart
state.items = state.items.map((item) => {
return item.name === product.name
? { ...item, quantity: product.quantity }
: item;
});
} else {
// If the product is new, add it to the cart
state.items.push(product);
}
},
// Reducer function: "deleteFromCart"
deleteFromCart: (state, action) => {
const product = action.payload;
// Filter out the product to be deleted from the cart based on its name
state.items = state.items.filter((item) => item.name !== product.name);
},
},
});
export const { addToCart, deleteFromCart } = cartSlice.actions;
export default cartSlice.reducer;
useContext
import { useState, useContext, createContext } from "react";
// Create Context
export const CartContext = createContext({});
// Create useContext function
export const useCartContext = () => {
return useContext(CartContext);
};
// Defualt Value in Cart
const initialCart = {
items: [],
};
const CartProvider = ({ children }) => {
const [cart, setCart] = useState(initialCart);
// Add & Update a Item to cart
const addToCart = (product) => {
const productExistsInCart = cart.items.some(
(item) => item.name === product.name
);
if (productExistsInCart) {
// Product with the same name already exists in the cart
setCart((prev) => {
const updatedCartItems = prev.items.map((item) =>
item.name === product.name
? { ...item, quantity: product.quantity}
: item
);
return {
...prev,
items: updatedCartItems,
};
});
} else {
// Product with the same name does not exist in the cart, add a new item
setCart((prev) => ({
...prev,
items: [...prev.items, product],
}));
}
};
// Delete a item from cart
const deleteFromCart = (product) => {
setCart((prev) => ({
...prev,
items: prev.items.filter((item) => item.name !== product.name),
}));
};
// Map all fucntion and parameter to useContext
const cartStore = {
cart,
cartAction: {
addToCart,
deleteFromCart,
},
};
return (
<CartContext.Provider value={cartStore}>{children}</CartContext.Provider>
);
};
export default CartProvider;