Replies: 2 comments 6 replies
-
why would you need react-query to fetch images? The |
Beta Was this translation helpful? Give feedback.
-
I have a use case, but it's not difficult once you learn how, to do what TkDodo suggests of caching the base64 encoded image. The use case: Basically, when the pokemon data loads, it then passes the image url to a PokemonCard component which loads the img. Well, the browser doesn't fetch the image url until after the img is actually added to the DOM and when testing a slow 3G network, the pokemon card and the data shows up and then 2 seconds later the image appears. I tried all kinds of solutions from watching an imageRef, to preloading and waiting for a promise to resolve, to using the onload event of the img element. None of these work because the img is already in the DOM but the actual image is not fetched by the browser yet. So what worked is actually fetching the image with react-query in my usePokemon hook and using the status of that fetch to show the loading card until the image is actually fetched and cached. I used a dependent query. TkDodo's response above, helped me figure out the last piece of it. Here is the code. usePokemon.ts import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import { POKEMON_API_URL, POKEMON_CACHE_KEY } from '../constants'
import { Pokemon } from '../types'
export default function usePokemon() {
const [id, setId] = useState(1)
const {
data: pokemon,
error,
isLoading,
} = useQuery<Pokemon>({
queryKey: [POKEMON_CACHE_KEY, id],
queryFn: () => fetch(`${POKEMON_API_URL}/${id}`).then((res) => res.json()),
})
const imageUrl = pokemon?.sprites?.front_default
const {
data: pokemonImage,
status,
fetchStatus,
error: imageError,
} = useQuery<string>({
queryKey: ['pokemon-image', id],
queryFn: () =>
fetch(`${imageUrl}`).then(async (res) => {
const blob = await res.blob()
const base64 = URL.createObjectURL(blob)
return base64
}),
enabled: !!imageUrl,
refetchOnWindowFocus: false,
})
return {
pokemon,
error,
isLoading,
imageError,
setId,
pokemonImage,
status,
fetchStatus,
}
} Used in PokemonApp.ts const PokemonApp = () => {
const [isReady, setIsReady] = useState(false)
const { pokemon, pokemonImage, status, error, setId, isLoading } =
usePokemon()
useEffect(() => {
if (status === 'success' && !isLoading) {
setIsReady(true)
}
}, [status, isLoading])
return (
<div className="mt-24 grid place-items-center">
{isReady ? (
<PokemonCard data={pokemon} error={error} image={pokemonImage} />
) : (
<Card>
<Loading />
</Card>
)}
<ButtonGroup handleSetId={setId} />
</div>
)
} I'm sure there are some issues with it that I need to work out but it is the basic idea and is working for me right now. |
Beta Was this translation helpful? Give feedback.
-
Would be great if there was some sort of integration between fetching images from a URL and React Query. I'm not sure how one would integrate this into
<img>
, but I think that would be a great feature if it worked out somehow. Is this possible currently?Beta Was this translation helpful? Give feedback.
All reactions