T
TanStack2y ago
afraid-scarlet

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
old-apricot
old-apricot2y ago
what type is data.messages
rare-sapphire
rare-sapphire2y ago
data.messages is likely undefined at runtime ...
afraid-scarlet
afraid-scarletOP2y 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
ambitious-aqua
ambitious-aqua2y ago
Do a console log in the select to inspect your data. There might be something wrong!
afraid-scarlet
afraid-scarletOP2y 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
ambitious-aqua
ambitious-aqua2y ago
Do a reproduction and one might be able to help you
afraid-scarlet
afraid-scarletOP2y ago
Ok, I will try
equal-jade
equal-jade2y 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.
afraid-scarlet
afraid-scarletOP2y 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
equal-jade
equal-jade2y 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.
afraid-scarlet
afraid-scarletOP17mo 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?