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:
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
Use Optional chaining (?) to access when dealing with nested objects or when accessing properties of objects returned by API calls.
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:
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.