Uncaught TypeError: Cannot read properties of undefined (reading '_id')

Viewed 40

When I login, I get a white page with the error ChatLogics.js:2 Uncaught TypeError: Cannot read properties of undefined (reading '_id'). The weird thing is that when I reload the page once, the error disappears. Why would the _id be undefined just after logged in and not on the reload ? which _id is undefined ? the users[0]._id or the loggedUser._id?

This is the ChatLogics.jsx file:

export const getSender = (loggedUser, users) => {
    return users[0]._id === loggedUser._id ? users[1].name : users[0].name; // Si le loggedUser a le même id que le user 0, alors afficher le nom de l'user 1 sinon afficher le nom de l'user 0
};

export const getSenderFull = (loggedUser, users) => {
    return users[0]._id === loggedUser._id ? users[1] : users[0]; // Si le loggedUser a le même id que le user 0, alors afficher le nom de l'user 1 sinon afficher le nom de l'user 0
};

export const isSameSender = (messages, message, i, userId) => {
    return (
        i < messages.length - 1 && //si l'index est < au nombre de messages - 1
        (messages[i + 1].sender._id !== message.sender._id || // si le prochain message n'est pas égal au sender actuel
        messages[i + 1].sender._id === undefined) && // ou si le prochain message n'est pas défini
        messages[i].sender._id !== userId // et si le sender message de l'index ne correspond à l'id de l'utilisateur courrant
    );
};

export const isLastMessage = (messages, message, i, userId) => {
    return (
        i === messages.length - 1 && // on vérifie si l'index est égal à celui du dernier message
        messages[messages.length - 1].sender._id !== userId && // on vérifie si l'id du dernier message est le même que celui de l'utilisateur connecté
        messages[messages.length - 1].sender._id // on vérifie si l'id du dernier message existe
    );
};

export const isSameSenderMargin = (messages, message, i, userId) => {
    if (
        i < messages.length - 1 &&
        messages[i + 1].sender._id === message.sender._id &&
        messages[i].sender._id !== userId
    )
    return 33; // mettre une marge de 33
    else if (
        (i < messages.length - 1 &&
            messages[i + 1].sender._id !== message.sender._id &&
            messages[i].sender._id !== userId) ||
        (i === messages.length - 1 && messages[i].sender._id !== userId)
    )
    return 0; // mettre une marge de 0
    else return "auto";
};

export const isSameUser = (messages, message, i) => {
    return i > 0 && messages[i - 1].sender._id === message.sender._id // si i est inférieur à 0 et que l'id du sender du message précédent est le même que celui de l'actuel
};

This is the MyChats.jsx file where getSender is called:

import { Box, Button, Stack, Text, useToast } from '@chakra-ui/react';
import { AddIcon } from '@chakra-ui/icons';
import React, { useState, useEffect } from 'react'
import { ChatState } from '../context/ChatProvider'
import axios from 'axios';
import ChatLoading from './ChatLoading';
import { getSender } from '../config/ChatLogics';
import GroupChatModal from './miscellaneous/GroupChatModal';

const MyChats = ({ fetchAgain }) => {
  const [loggedUser, setLoggedUser] = useState();
  const { user, selectedChat, setSelectedChat, chats, setChats } = ChatState();

  const toast = useToast();

  const fetchChats = async () => {
        try {
            const config = {
                headers: {
                    Authorization: `Bearer ${user.token}`
                }
            };

            const { data } = await axios.get("/api/chat", config);

            setChats(data);
        } catch (error) {
            toast({
                title: 'Error occured',
                description: 'Failed to load the chats',
                status: 'error',
                duration: 5000,
                isClosable: true,
                position: "bottom-left"
            });
        }
    };

    useEffect(() => {
      setLoggedUser(JSON.parse(localStorage.getItem('userInfo')));
      fetchChats();
    }, [fetchAgain]);
  return (
    <Box
      display={{ base: selectedChat ? "none" : "flex", md: "flex" }}
      flexDirection="column"
      alignItems="center"
      p={3}
      bg="white"
      w={{ base: "100%", md: "31%" }}
      borderRadius="lg"
      borderWidth="1px"
    >
      <Box
        pb={3}
        px={3}
        fontSize={{ base: "28px", md: "30px" }}
        fontFamily="Work sans"
        display="flex"
        w="100%"
        justifyContent="space-between"
        alignItems="center"
      >
        My Chats
        <GroupChatModal>
          <Button
          display="flex"
          fontSize={{ base: "17px", md: "10px", lg: "17px" }}
          rightIcon={<AddIcon />}
          >
            New Group Chat
          </Button>
        </GroupChatModal>
      </Box>
      <Box
        display="flex"
        flexDirection="column"
        p={3}
        bg="#F8F8F8"
        w="100%"
        h="100%"
        borderRadius="lg"
        overflowY="hidden"
      >
        {chats ? (
          <Stack overflowY="scroll">
            {chats.map((chat) => (
              <Box
                onClick={() => setSelectedChat(chat)}
                cursor="pointer"
                bg={selectedChat === chat ? "#494A93" : "#E8E8E8"}
                color={selectedChat === chat ? "white" : "black"}
                px={3}
                py={2}
                borderRadius="lg"
                key={chat._id}
              >
                <Text>
                  {!chat.isGroupChat 
                    ? getSender(loggedUser, chat.users)
                    : (chat.chatName)}
                </Text>
              </Box>
            ))}
          </Stack>
        ) : (
          <ChatLoading />
        )}
      </Box>
    </Box>
  )
}

export default MyChats
1 Answers

You can put a Optional Chaining operator ? in order to avoid a read properties of undefined error.

export const getSender = (loggedUser, users) => {
    return users[0]?._id === loggedUser?._id ? users[1]?.name : users[0].name; 
};
Related