skip to Main Content

I am trying to access properties of an object from an array of objects I get after fetching them from backend bust as soon as I try to access the property ,it logs the object itself as undefined which was logged successfully if I never access the property in console.

here is the code and I commented where it gets the error:

import { useEffect, useState } from "react";
import toast from "react-hot-toast";


const useGetConversations = () => {
    const [loading, setLoading] = useState(false);
    const [conversations, setConversations] = useState([]);

    useEffect(() => {
        const getConversations = async () => {
            setLoading(true);
            try {
                const res = await fetch("/api/users");
                const data = await res.json();
                if (data.error) {
                    throw new Error(data.error);
                }
                
                setConversations(data);
                
            } catch (error) {
                toast.error(error.message);
            } finally {
                setLoading(false);
                
            }
        };

        getConversations();
    }, []);
    console.log("before return statement",conversations[0]);// it runs correctly only if i am not trying to acces any property
    console.log("before return statement",conversations[0].name);
    return { loading, conversations };
    
};
export default useGetConversations;

here are the error screenshots:

enter image description here

I expect to run the files successfully:

import useGetConversations from "../../hooks/useGetConversations";
import { getRandomEmoji } from "../../utils/emojis";
import Conversation from "./Conversation";

const Conversations = () => {
    const { loading, conversations } = useGetConversations();

    //could log the array of objects succesfully
    // console.log(conversations);
    //could log a single object successfully
    // console.log(conversations[0]); 
    //could not log the object properties successfully and previous lines are also defined as undefined 
    // console.log(conversations[0].name); 
    return (
        <div className='py-2 flex flex-col overflow-auto'>
            {conversations.map((conversation, idx) => (
                <Conversation
                    key={conversation._id}
                    conversation={conversation}
                    emoji={getRandomEmoji()}
                    lastIdx={idx === conversations.length - 1}
                />
            ))}

            {loading ? <span className='loading loading-spinner mx-auto'></span> : null}
        </div>
    );
};
export default Conversations;

2

Answers


  1. Use Optional chaining (?) to access when dealing with nested objects or when accessing properties of objects returned by API calls.

    import { useEffect, useState } from "react";
    import toast from "react-hot-toast";
    
    
    const useGetConversations = () => {
        const [loading, setLoading] = useState(false);
        const [conversations, setConversations] = useState([]);
    
        useEffect(() => {
            const getConversations = async () => {
                setLoading(true);
                try {
                    const res = await fetch("/api/users");
                    const data = await res.json();
                    if (data.error) {
                        throw new Error(data.error);
                    }
                    
                    setConversations(data);
                    
                } catch (error) {
                    toast.error(error.message);
                } finally {
                    setLoading(false);
                    
                }
            };
    
            getConversations();
        }, []);
        console.log("before return statement",conversations[0]);
        console.log("before return statement",conversations[0]?.name);
        return { loading, conversations };
        
    };
    export default useGetConversations;
    
    Login or Signup to reply.
  2. it would be better to do a conditional rendering of the component. If the hook useGetCOnversations retrieved empty, the component which uses the hook will do something like:

    if (conversations.length === 0) {
      return <Fallback />
    }

    Fallback being some kind of auxilar component, just like a loading would do. I think optional chaining its okay, but I would not recommend using it everytime. Code can get very messy working with complex objects.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search