A simple example for react redux.
store/index.jsx
import { createStore } from "redux";
const counterReducer = (state = { counter: 0 }, action) => {
if (action.type === "increment") {
return {
counter: state.counter + 1,
};
}
if (action.type === "decrement") {
return {
counter: state.counter - 1,
};
}
return state;
};
const store = createStore(counterReducer);
export default store;
We create a small store for counter using Redux then we export.
src/index.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import store from "./store/index";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>,
);
src/components/Counter.jsx
import classes from "./Counter.module.css";
import { useSelector } from "react-redux";
const Counter = () => {
const counter = useSelector((state) => state.counter);
const toggleCounterHandler = () => {};
return (
<main className={classes.counter}>
<h1>Redux Counter</h1>
<div className={classes.value}>{counter} </div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;
What is we want to add action to counter.jsx component with class based component.
// import { Component } from "react";
import { connect } from "react-redux";
import classes from "./Counter.module.css";
import { useSelector, useDispatch } from "react-redux";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const toggleCounterHandler = () => {};
const incrementHandler = () => {
dispatch({ type: "increment" });
};
const decrementHandler = () => {
dispatch({ type: "decrement" });
};
return (
<main className={classes.counter}>
<h1>Redux Counter</h1>
<div className={classes.value}>{counter} </div>
<div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={decrementHandler}>Decrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
// class Counter extends Component {
// incrementHandler() {
// this.props.increment();
// }
// decrementHandler() {
// this.props.decrement();
// }
// toggleCounterHandler() {}
// render() {
// return (
// <main className={classes.counter}>
// <h1>Redux Counter</h1>
// <div className={classes.value}>{this.props.counter} </div>
// <div>
// <button onClick={this.incrementHandler.bind(this)}>Increment</button>
// <button onClick={this.decrementHandler.bind(this)}>Decrement</button>
// </div>
// <button onClick={this.toggleCounterHandler}>Toggle Counter</button>
// </main>
// );
// }
// }
// const mapStateToProps = (state) => {
// return {
// counter: state.counter,
// };
// };
// const mapDispatchToProps = (dispatch) => {
// return {
// increment: () => dispatch({ type: "increment" }),
// decrement: () => dispatch({ type: "decrement" }),
// };
// };
export default Counter;
// export default connect(mapStateToProps, mapDispatchToProps)(Counter);
Here commented parts are class based component with redux.
Attaching Payloads to Actions (Passing parameters)
store/index,js
if (action.type === "increase") {
return {
counter: state.counter + action.amount,
};
}
components/counters.jsx
const increase = () => {
dispatch({ type: "increase", amount: 5 });
};
Adding State Slices
Add reduxjs/toolkit package to your project
After add this package we need to change some code in store/index.js file.
If you check the above code this part of code has different code.
import { configureStore, createSlice } from "@reduxjs/toolkit";
const intialState = { counter: 0, showCounter: true };
const counterSlice = createSlice({
name: "counter",
initialState: intialState,
reducers: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
increase(state, action) {
state.counter = state.counter + action.amount;
},
toggleCounter(state) {
state.showCounter = !state.showCounter;
},
},
});
const store = configureStore({
reducer: counterSlice.reducer,
});
export default store;
With this code now we need to change counter.jsx file.
import classes from "./Counter.module.css";
import { useSelector, useDispatch } from "react-redux";
import { counterActions } from "../store/index";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const showCounter = useSelector((state) => state.showCounter);
const incrementHandler = () => {
dispatch(counterActions.increment());
};
const increase = () => {
dispatch(counterActions.increase(10));
};
const decrementHandler = () => {
dispatch(counterActions.decrement());
};
const toggleCounterHandler = () => {
dispatch(counterActions.toggleCounter());
};
return (
<main className={classes.counter}>
<h1>Redux Counter</h1>
{showCounter && <div className={classes.value}>{counter} </div>}
<div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={decrementHandler}>Decrement</button>
<button onClick={increase}>Increament by 5</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;
Managing multiple States
store/index.js
// import { createStore } from "redux";
import { configureStore, createSlice } from "@reduxjs/toolkit";
const intialCounterState = { counter: 0, showCounter: true };
const counterSlice = createSlice({
name: "counter",
initialState: intialCounterState,
reducers: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
increase(state, action) {
state.counter = state.counter + action.payload;
},
toggleCounter(state) {
state.showCounter = !state.showCounter;
},
},
});
const initialAuthState = {
isAuthenticated: false,
};
const authSlice = createSlice({
name: "authentication",
initialState: initialAuthState,
reducers: {
login(state) {
state.isAuthenticated = true;
},
logout(state) {
state.isAuthenticated = false;
},
},
});
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
auth: authSlice.reducer,
},
});
export const counterActions = counterSlice.actions;
export const authActions = authSlice.actions;
export default store;
In this we managed multiple state authSlice and counterSlice
All these in action