Next.js Discord

Discord Forum

TypeError: Failed to parse URL from /api/recommendations/sAvdpLZ4kwN1

Answered
Chinese perch posted this in #help-forum
Open in Discord
Avatar
Chinese perchOP
I was getting this error on Nextjs 14 as well as on 15. I'm aware that this kind of error occurs when we fetch a relative URL in Server Component but I'm fetching this URL in a Client Component.
// src/app/rec/[id]/page.tsx
import { Recommendations } from '@/app/rec/Recommendations';

export default async function RecommendationsPage({ params }: { params: Promise<{ id: string }> }) {
    const { id } = await params;
    return (
        <div>
            <Recommendations id={id} />
        </div>
    );
}

// src/app/rec/Recommendations.tsx
'use client';

import { useZustandStore } from '@/util/store';
import { TrackCard } from '../TrackCard';

export function Recommendations({ id }: { id: string }) {
    const recommendedTracks = useZustandStore(state => state.recommendedTracks);
    const setRecommendedTracks = useZustandStore(state => state.setRecommendedTracks);

    const fetchStoredTracks = async () => {
        const res = await fetch(`/api/recommendations/${id}`);
        const data = await res.json();
        if (data) {
            setRecommendedTracks(data.tracks);
        } else {
            setRecommendedTracks(null);
        }
    };

    if (recommendedTracks.length === 0) {
        fetchStoredTracks();
    }

    return (
        <div>
            {recommendedTracks.map(track => {
                return <TrackCard key={track.id} track={track} />;
            })}
        </div>
    );
}
Answered by James4u (Tag me if needed)
one of followings should fix your problem
- wrap your fetch logic inside useEffect()
- add client-only to your page
- use next/dynamic with ssr: false
View full answer

14 Replies

Avatar
one of followings should fix your problem
- wrap your fetch logic inside useEffect()
- add client-only to your page
- use next/dynamic with ssr: false
Answer
Avatar
@Chinese perch
note that client components are still rendered on the server
Avatar
Chinese perchOP
@James4u (Tag me if needed) Thanks. I ended up using useEffect and it fixed the issue. However, I kind of don't like using this hook. Couldn't find any docs on client-only and for the dynamic import I'm getting the following TS error:

Argument of type '() => Promise<typeof import("e:/orpheus/src/app/rec/Recommendations")>' is not assignable to parameter of type 'DynamicOptions<{}> | Loader<{}>'.
  Type '() => Promise<typeof import("e:/orpheus/src/app/rec/Recommendations")>' is not assignable to type '() => LoaderComponent<{}>'.
    Type 'Promise<typeof import("e:/orpheus/src/app/rec/Recommendations")>' is not assignable to type 'LoaderComponent<{}>'.
      Type 'typeof import("e:/orpheus/src/app/rec/Recommendations")' is not assignable to type 'ComponentType<{}> | ComponentModule<{}>'
Also, what's the point of having 'use client' if it ends up being executed on server?
Avatar
well, client-only is a different thing from dynamic import
next/dynamic with ssr: false ⬆️
use client indicates the root of the client boundry - you can use hooks, event handlers in your client component - you can think it as "use interactive"
it doesn't mean it's rendered only on the client end
Avatar
Chinese perchOP
yes, I got that part 2 & 3 are different solutions, I'm just saying the dynamic import is giving me a TS error. And I can't find anything about 'client-only' on googling
Avatar
show me how you tried to do lazy loading with next/dynamic
Avatar
Chinese perchOP
@James4u (Tag me if needed) here
import dynamic from 'next/dynamic';

const Recommendations = dynamic(() => import('@/components/Recommendations'), { ssr: false });

export default async function RecommendationsPage({ params }: { params: Promise<{ id: string }> }) {
    const { id } = await params;
    return (
        <div>
            <Recommendations id={id} />
        </div>
    );
}
Image