I have the following API Call:
const router = useRouter();
const { albumQuery } = router.query;
const [albums, setAlbums] = useState([]);
const fetchAlbumsHandler = useCallback(async () => {
setIsLoading(true);
setError(null);
try {
const url = `http://ws.audioscrobbler.com/2.0/?method=album.search&album=${albumQuery}&api_key=MY_API_KEY&format=json`;
const res = await fetch(url);
const data = await res.json();
if (!res.ok) {
throw new Error("Something went wrong!");
}
const jsonAlbums = data.map(
// JSON business Logic
);
setAlbums(transformedAlbums);
} catch (error) {
setError(error.message);
}
setIsLoading(false);
}, []);
With the corresponding useEffect function:
useEffect(() => {
fetchAlbumsHandler();
}, [fetchAlbumsHandler]);
However, the API call takes ${albumQuery}
as undefined on the first render due to NextJS implementation details. Is there a way for me to access the variable on the first render?
CodePudding user response:
No, if the albumQuery
isn't available on the initial render then the code should handle waiting for it to become available.
The existing code is assuming albumQuery
is available on the initial render and attempts to close it over in the useCallback
hook. After this the useEffect
hook is called and since fetchAlbumsHandler
is now a stable reference the useEffect
hook won't be retriggered nor will fetchAlbumsHandler
be re-memoized since the useCallback
hook has an empty dependency array.
Minimally albumQuery
appears to be a dependency for the useCallback
hook and/or the useEffect
hook. If fetchAlbumsHandler
isn't passed as a prop to children there's no real benefit to memoizing it. I suggest moving it into the useEffect
hook callback and using albumQuery
as a dependency.
Example:
const router = useRouter();
const { albumQuery } = router.query;
const [albums, setAlbums] = useState([]);
useEffect(() => {
const fetchAlbumsHandler = async () => {
setIsLoading(true);
setError(null);
try {
const url = `http://ws.audioscrobbler.com/2.0/?method=album.search&album=${albumQuery}&api_key=MY_API_KEY&format=json`;
const res = await fetch(url);
const data = await res.json();
if (!res.ok) {
throw new Error("Something went wrong!");
}
const jsonAlbums = data.map(
// JSON business Logic
);
setAlbums(transformedAlbums);
} catch (error) {
setError(error.message);
}
setIsLoading(false);
}
fetchAlbumsHandler();
}, [albumQuery]);