T
TanStack15mo ago
fascinating-indigo

useQuery - select return undefined data

Hello guys, I have a custom hooks who goes like this:
import { useQuery } from "@tanstack/react-query"

import axios from "@/config/axios"
import { Chat, IGiftedChat } from "../utils/types"

const useGetChat = (id: string) => {
const query = useQuery({
queryKey: ["chat", id],
queryFn: async () => {
const response = await axios.get<Chat>(`/chats/${id}`)
return response.data
},
select: (data): IGiftedChat => {
return {
id: data.id,
user: data.contact,
messages: data.messages.map((message) => ({
_id: data.id,
text: message.content,
createdAt: new Date(message.updatedAt),
user: {
_id: data.contact.id,
name: data.contact.firstname,
avatar: data.contact.avatar ?? undefined,
},
})),
}
},
})

return query
}

export default useGetChat
import { useQuery } from "@tanstack/react-query"

import axios from "@/config/axios"
import { Chat, IGiftedChat } from "../utils/types"

const useGetChat = (id: string) => {
const query = useQuery({
queryKey: ["chat", id],
queryFn: async () => {
const response = await axios.get<Chat>(`/chats/${id}`)
return response.data
},
select: (data): IGiftedChat => {
return {
id: data.id,
user: data.contact,
messages: data.messages.map((message) => ({
_id: data.id,
text: message.content,
createdAt: new Date(message.updatedAt),
user: {
_id: data.contact.id,
name: data.contact.firstname,
avatar: data.contact.avatar ?? undefined,
},
})),
}
},
})

return query
}

export default useGetChat
when I try to use it like that:
const { data, isLoading } = useGetChat(params?.id as string)
const { data, isLoading } = useGetChat(params?.id as string)
I have undefined as the result below the result when I'm logging: data and error undefined [TypeError: Cannot read property 'map' of undefined] Can someone help me?
12 Replies
itchy-amethyst
itchy-amethyst15mo ago
what type is data.messages
like-gold
like-gold15mo ago
data.messages is likely undefined at runtime ...
fascinating-indigo
fascinating-indigoOP15mo ago
Really sorry I didn't get the notifications... thanks for taking the time to respond. Here is the type of message:
interface Message {
id: number
chatId: number
senderId: number
receiverId: number
content: string
is_read: boolean
updatedAt: string
}
interface Message {
id: number
chatId: number
senderId: number
receiverId: number
content: string
is_read: boolean
updatedAt: string
}
Hi, thanks for taking the time to respond, sorry to respond this late. I'm a bit confused, can you explain please? because I thought that select happens after query function was made
optimistic-gold
optimistic-gold15mo ago
Do a console log in the select to inspect your data. There might be something wrong!
fascinating-indigo
fascinating-indigoOP15mo ago
When I do a console.log(data) I get the data but it's when I try to transform those that I get undefined
optimistic-gold
optimistic-gold15mo ago
Do a reproduction and one might be able to help you
fascinating-indigo
fascinating-indigoOP15mo ago
Ok, I will try
xenial-black
xenial-black15mo ago
You're lying to TS. You're making a strong assumption here that params.id will be always present by the time you call this query, but TS tells you it may be not. That's why you casting it to a string. Actually, your query must be error-proof. If you're using id as an argument to your query, you must check for it's presence either by providing enabled: !!id property that will only fire the query when id is there, or by using a skipToken. If you will follow this simple rule you will not need to type anything but the hook arguments and await axios.get<Chat>(/chats/${id}) this part. Let TS do its job for you. It may be related or unrelated to your problem. Who knows? But lying about your type has put you into this situation in the first place. Maybe your id is not present at the first render, and you run this query with undefined as id, and that's why you get this error. I would recommend checking for an id and working your way down the chain to debug this.
fascinating-indigo
fascinating-indigoOP15mo ago
I'm using this with React Native, i'm trying to build a chat app. I used this:
const handlePress = (item: Chat) => {
router.push({
pathname: "/chats/[id]",
params: { id: item.id },
})
}
const handlePress = (item: Chat) => {
router.push({
pathname: "/chats/[id]",
params: { id: item.id },
})
}
And in the ChatScreen I get the id from the params and pass it to the hook. I try the enabled: !!id but it didn't work. When I don't use select, it works pretty well, the problem occured when I started using select I'm doing this transformation to fit the React Native Gifted Chat package
xenial-black
xenial-black15mo ago
Ok so we eliminated one step. Now console log the data you get in the select. Maybe you missed the response structure. Take a close look at messages array, as it's the only field that you're mapping. Maybe 1 item doesn't have this array, try to check it. Try to optionally access data?.messages in select . Maybe when there's no messages in the chat your BE doesn't send you this field and you get this error.
fascinating-indigo
fascinating-indigoOP14mo ago
My apologies guys. the problem was coming from the API. In the route to get a chat I though I was returning an object but I was returning an array of objects

Did you find this page helpful?