Here, I am going to create the Slice and later import it into my redux store to manage the clean code.
import { createSlice } from “@reduxjs/toolkit”;
In the above code,
createSlice: A tool from Redux Toolkit that makes it easier to create a Redux slice by putting actions, reducers, and initial state together in one step.
const initialState = {
status: false,
userData: null
}
initialState: Shows the starting state of the login section. status: Tells if a user is logged in (true) or logged out (false). userData: Stores user information (like profile) when logged in.Starts as null.
const authSlice = createSlice({
name: “auth”,
initialState,
reducers: {
login: (state, action)=> {
state.status = true;
state.userData = action.payload.userData
},
logout: (state) => {
state.status = false;
state.userData = null
}
}
})
authSlice:
name: The name of the slice, used as a start for action types (auth/login, auth/logout).
initialState: The starting state for the slice.
let’s break the why I am using the initialState instead of the direct importing of its properties.
initialState is a single object that encapsulates the entire state structure of the slice. By defining and using it as a single entity, we make the code easier to reuse and modify.
If we directly import status
and userData
separately, we would lose the centralized definition of the state. Every time we want to update or extend the state, so we would need to ensure consistency in multiple places.
For Example
const initialState = {
status: false,
userData: null
};
If we later decide to add a new property (e.g., role
), we only need to modify initialState
in one place.
When we pass the initialstate to createSlice, we abstract away the implementation details of the state. This makes the slice more readable and maintainable.
If we pass status and userData directly, our code would become verbose and harder to manage, as shown below:
const authSlice = createSlice({
name: “auth”,
initialState: {
status: false,
userData: null
},
reducers: { … }
});
With initialState, the code stays cleaner:
const authSlice = createSlice({
name: “auth”,
initialState,
reducers: { … }
});
By defining the initialState object, we establish a single source of truth for the state structure. If we import status and userData separately, we risk introducing inconsistencies, especially if they are used or modified independently.
Using initialState prepares our codebase for future enhancements. For example:
const initialState = {
status: false,
userData: null,
role: “guest”,
token: null
};
We can easily add new properties without altering the slice’s core structure. If status and userData were imported separately, we would need to refactor code everywhere to include new properties.
reducers: Shows the actions and how they change the state.
Reducers:
login:
Takes the current state and an action as arguments.
indicating status to true, showing the user is logged in.
Updates userData with action.payload.userData (data sent when the action is dispatched).
logout:
Changes status to false, indicating the user is logged out.
Sets userData back to null.
export const { login, logout } = authSlice.actions;
Exports the login
and logout
action creators, which can be dispatched to update the state.
export default authSlice.reducer;
In this code, I am exporting the reducer function, which will be used in the Redux store.