Practice Redux
- First, you need to prepare Redux Toolkits & react-redux:
npm install @reduxjs/toolkit react-redux
-Creating Slice Reducer with the name file counterSlice.js in the redux/slices Folder
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
value: 0
};
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
}
}
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
-Creating a Store with Redux (store.js) Toolkit in Folder redux:
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './slices/counterSlice';
const store = configureStore({
reducer: {
counter: counterReducer
}
});
export default store;
- configure the <Provider> component of react-redux in the Root Element
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { Provider } from 'react-redux';
import store from "./redux/store.js";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
- Implementation into react components
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from "../redux/slices/counterSlice";
function CounterComponent() {
const count = useSelector(state => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<h2>Counter</h2>
<div>
<button onClick={() => dispatch(increment())}>Increment</button>
<span>{count}</span>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
<div>
<input
type="number"
onChange={(e) => dispatch(incrementByAmount(parseInt(e.target.value) || 0))}
placeholder="Enter value"
/>
<button onClick={() => dispatch(incrementByAmount(5))}>Add 5</button>
</div>
</div>
);
}
export default CounterComponent;
useSelector
is used to select specific parts of the state from the Redux store within a React component. It
allows React components to subscribe to specific parts of the state and will re-render
whenever the related state changes.
useDispatch
is used to access the Redux dispatch function within a React component. This dispatch
function is used to send actions to the Redux store, which will cause state changes.
1. Redux AsyncThunk (for communication with API)
-Creating a User Slice(userSlice.js) and fetchUser with AsyncThunk in the
redux/slicer Folder
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const fetchUser = createAsyncThunk("user/fetchUser", async () => {
try {
const response = await axios.get(
`https://jsonplaceholder.typicode.com/users`
);
return response.data;
} catch (error) {
return error;
}
});
const userSlice = createSlice({
name: "user",
initialState: {
data: [],
loading: false,
error: null,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.loading = true;
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
state.error = null;
})
.addCase(fetchUser.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
},
});
export default userSlice.reducer;;
- Add userSlice in Store (store.js)
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './slices/counterSlice';
import userReducer from './slices/userSlice';
const store = configureStore({
reducer: {
counter: counterReducer
user: userReducer,
}
});
export default store;
- Implementation into react components
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchUser } from "../redux/slices/userSlice";
function UserComponent() {
const userData = useSelector((state) => state.user.data);
const isLoading = useSelector((state) => state.user.loading);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchUser());
}, [dispatch]);
if (isLoading) {
return <div>Loading...</div>;
}
console.log(userData);
return (
<div>
<h2>User Details</h2>
{userData?.map((item) => (
<div key={item.id}>
<span>Name: {item.name}</span>
<span> - </span>
<span>Email: {item.email}</span>
</div>
))}
</div>
);
}
export default UserComponent;
https://redux.js.org/tutorials/fundamentals/part-8-modern-redux
https://www.youtube.com/watch?v=u3KlatzB7GM&list=PL0Zuz27SZ-6M1J5I1w2-
uZx36Qp6qhjKo