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 properties- userof type- Userand- tokenof type- string.
- setFriendsaction now accepts an object with a- friendsproperty of type- string[].
- setPostsaction now accepts an object with a- postsproperty of type- Post[].
- setPostaction now accepts an object with a- postproperty of type- Post.
 
- 
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;