Redux Setup
Redux Setup
State folder -> index.js
import { createSlice } from "@reduxjs/toolkit";
// Define the initial state of the application
const initialState = {
mode: "light", // Represents the current theme mode ("light" or "dark")
user: null, // Represents the currently logged-in user
token: null, // Represents the authentication token
posts: [], // Represents a list of posts
};
// Create a slice of the Redux store using the createSlice function from Redux Toolkit
export const authSlice = createSlice({
name: "auth", // Name of the slice
initialState, // Initial state of the slice
reducers: {
setMode: (state) => {
// Toggle the theme mode between "light" and "dark"
state.mode = state.mode === "light" ? "dark" : "light";
// Here, `state.mode` represents the previous theme mode (mode: "light"),
// and `state.mode === "light" ? "dark" : "light"` represents the new theme mode.
},
setLogin: (state, action) => {
// Set the logged-in user and authentication token
state.user = action.payload.user;
state.token = action.payload.token;
// Here, `action.payload` represents the data passed when dispatching this action.
// `action.payload.user` represents the user data,
// and `action.payload.token` represents the authentication token.
},
setLogout: (state) => {
// Clear the logged-in user and authentication token
state.user = null;
state.token = null;
},
setFriends: (state, action) => {
if (state.user) {
// Set the friends of the logged-in user
state.user.friends = action.payload.friends;
// Here, `action.payload.friends` represents the list of friends passed in the action payload.
} else {
console.error("user friends non-existent :(");
// If there is no logged-in user, an error message is logged to the console.
}
},
setPosts: (state, action) => {
// Set the list of posts
state.posts = action.payload.posts;
// Here, `action.payload.posts` represents the list of posts passed in the action payload.
},
setPost: (state, action) => {
// Update a specific post in the list of posts
const updatedPosts = state.posts.map((post) => {
if (post._id === action.payload.post._id) {
// If the post's _id matches the updated post's _id,
// replace it with the updated post in the new array
return action.payload.post;
}
return post;
});
state.posts = updatedPosts;
// Here, `action.payload.post` represents the updated post passed in the action payload.
},
},
});
// Extract the actions generated by the createSlice function
export const {
setMode,
setLogin,
setLogout,
setFriends,
setPosts,
setPost,
} = authSlice.actions;
export default authSlice.reducer;We are using index.ts so we should modify this and using interfaces in TypeScript is a good practice for defining the types of your state and payload objects.
-
Added the
Userinterface: Represents the structure of a user object with propertiesid,name, andfriends. -
Added the
Postinterface: Represents the structure of a post object with properties_idand any other relevant post properties. -
Added the
AuthStateinterface: Represents the structure of the authentication state object, including propertiesmode,user,token, andposts. -
Updated the
initialStatedeclaration to use theAuthStateinterface. -
Updated the payload types in the action creators:
setLoginaction now accepts an object with propertiesuserof typeUserandtokenof typestring.setFriendsaction now accepts an object with afriendsproperty of typestring[].setPostsaction now accepts an object with apostsproperty of typePost[].setPostaction now accepts an object with apostproperty of typePost.
-
Modified the
setFriendsreducer to use theproducefunction from theimmerlibrary to handle the immutability of the nesteduserobject. Theproducefunction ensures that the state is not modified directly and allows you to make
import { createSlice, Draft, PayloadAction } from "@reduxjs/toolkit";
import produce from "immer";
interface User {
id: string;
name: string;
friends: string[];
}
interface Post {
_id: string;
// Other post properties
}
interface AuthState {
mode: string;
user: User | null;
token: string | null;
posts: Post[];
}
const initialState: AuthState = {
mode: "light",
user: null,
token: null,
posts: [],
};
export const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
setMode: (state) => {
state.mode = state.mode === "light" ? "dark" : "light";
},
setLogin: (
state,
action: PayloadAction<{ user: User; token: string }>
) => {
state.user = action.payload.user;
state.token = action.payload.token;
},
setLogout: (state) => {
state.user = null;
state.token = null;
},
setFriends: (state, action: PayloadAction<{ friends: string[] }>) => {
state.user = produce(state.user, (draft: Draft<User | null>) => {
if (draft) {
draft.friends = action.payload.friends;
} else {
console.error("User object is null");
}
});
},
setPosts: (state, action: PayloadAction<{ posts: Post[] }>) => {
state.posts = action.payload.posts;
},
setPost: (state, action: PayloadAction<{ post: Post }>) => {
state.posts = state.posts.map((post) =>
post._id === action.payload.post._id ? action.payload.post : post
);
},
},
});
export const {
setMode,
setLogin,
setLogout,
setFriends,
setPosts,
setPost,
} = authSlice.actions;
export default authSlice.reducer;