I fetch JSON file from external API using React Query. Below is fetch hook.
import { QueryClient, QueryKey, useQuery } from "@tanstack/react-query";
let Tmdb: string;
if (typeof process.env.NEXT_PUBLIC_TMDBURL === "string") {
Tmdb = process.env.NEXT_PUBLIC_TMDBURL;
} else {
throw new Error("NEXT_PUBLIC_TMDBURL is not defined");
}
export const useFetchData = () => {
const queryClient = new QueryClient();
const queryKey: QueryKey = ["repoData"];
const { isLoading, error, data } = useQuery({
queryKey,
queryFn: async () => {
const response = await fetch(Tmdb, { method: "GET" });
const data = await response.json();
if (!response.ok) {
throw new Error("Network response was not ok");
}
if (isLoading) {
console.log("ローディング中です");
}
if (error) {
console.log("エラーです");
}
console.log(data);
return data;
},
});
return { data, isLoading, error };
};
And below one is the Component which use "useFetchData" hook.
import { QueryClient } from "@tanstack/react-query";
import { useFetchData } from "../hooks/useFetchData";
function PublishedMovieList() {
const queryClient = new QueryClient();
const { data, isLoading, error } = useFetchData();
// 取得した"data"のタイプを定義する
type FetchData = {
adult: boolean;
backdrop_path: string;
belongs_to_collection: null;
budget: number;
genres: { id: number; name: string }[];
homepage: string;
id: number;
imdb_id: string;
original_language: string;
original_title: string;
overview: string;
popularity: number;
poster_path: string;
production_panies: {
id: number;
logo_path: string;
name: string;
origin_country: string;
}[];
production_countries: { iso_3166_1: string; name: string }[];
release_date: Date;
revenue: number;
runtime: number;
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string;
title: string;
video: boolean;
vote_average: number;
vote_count: number;
};
// 取得したdataを配列にする
const movieList = (Object.keys(data) as (keyof FetchData)[]).map((keys) => {
return { keys: keys[data] };
});
console.log(movieList);
return (
<div>
<div>
<p className="text-3xl py-5 pl-5">公開中作品</p>
</div>
<div className="flex space-x-10 pl-5">
{movieList.map((item) => (
<section className="w-1/5" key={item.id}>
<img
src={`/${item.poster_path}`}
></img>
</section>
))}
</div>
</div>
);
}
export default PublishedMovieList;
And below one is "page.tsx" file.
import PublishedMovieList from "./ponents/PublishedMovieList";
import Sidebar from "./ponents/Sidebar";
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
export default function Home() {
return (
<QueryClientProvider client={queryClient}>
<main className="bg-indigo-950 min-h-screen min-w-full">
<div className="text-5xl py-10 pl-5 border-b border-white">
<h1>今日、何観る?</h1>
</div>
<div className="flex">
<div>
<Sidebar />
</div>
<div>
<PublishedMovieList />
</div>
</div>
</main>
</QueryClientProvider>
);
}
When I start dev environment,"Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported." displayed.
I use below languages. ・React ver18 ・Next.js ver14.1.0 ・TypeScript ver5
I'm beginner for coding.If you are hard to read code, I apologize.
I mented out the "useFetchData" file because I think there is cause in fetch process. But it doesn't improve anything...
Please help me.
I fetch JSON file from external API using React Query. Below is fetch hook.
import { QueryClient, QueryKey, useQuery } from "@tanstack/react-query";
let Tmdb: string;
if (typeof process.env.NEXT_PUBLIC_TMDBURL === "string") {
Tmdb = process.env.NEXT_PUBLIC_TMDBURL;
} else {
throw new Error("NEXT_PUBLIC_TMDBURL is not defined");
}
export const useFetchData = () => {
const queryClient = new QueryClient();
const queryKey: QueryKey = ["repoData"];
const { isLoading, error, data } = useQuery({
queryKey,
queryFn: async () => {
const response = await fetch(Tmdb, { method: "GET" });
const data = await response.json();
if (!response.ok) {
throw new Error("Network response was not ok");
}
if (isLoading) {
console.log("ローディング中です");
}
if (error) {
console.log("エラーです");
}
console.log(data);
return data;
},
});
return { data, isLoading, error };
};
And below one is the Component which use "useFetchData" hook.
import { QueryClient } from "@tanstack/react-query";
import { useFetchData } from "../hooks/useFetchData";
function PublishedMovieList() {
const queryClient = new QueryClient();
const { data, isLoading, error } = useFetchData();
// 取得した"data"のタイプを定義する
type FetchData = {
adult: boolean;
backdrop_path: string;
belongs_to_collection: null;
budget: number;
genres: { id: number; name: string }[];
homepage: string;
id: number;
imdb_id: string;
original_language: string;
original_title: string;
overview: string;
popularity: number;
poster_path: string;
production_panies: {
id: number;
logo_path: string;
name: string;
origin_country: string;
}[];
production_countries: { iso_3166_1: string; name: string }[];
release_date: Date;
revenue: number;
runtime: number;
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string;
title: string;
video: boolean;
vote_average: number;
vote_count: number;
};
// 取得したdataを配列にする
const movieList = (Object.keys(data) as (keyof FetchData)[]).map((keys) => {
return { keys: keys[data] };
});
console.log(movieList);
return (
<div>
<div>
<p className="text-3xl py-5 pl-5">公開中作品</p>
</div>
<div className="flex space-x-10 pl-5">
{movieList.map((item) => (
<section className="w-1/5" key={item.id}>
<img
src={`https://image.tmdb/t/p/w185/${item.poster_path}`}
></img>
</section>
))}
</div>
</div>
);
}
export default PublishedMovieList;
And below one is "page.tsx" file.
import PublishedMovieList from "./ponents/PublishedMovieList";
import Sidebar from "./ponents/Sidebar";
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
export default function Home() {
return (
<QueryClientProvider client={queryClient}>
<main className="bg-indigo-950 min-h-screen min-w-full">
<div className="text-5xl py-10 pl-5 border-b border-white">
<h1>今日、何観る?</h1>
</div>
<div className="flex">
<div>
<Sidebar />
</div>
<div>
<PublishedMovieList />
</div>
</div>
</main>
</QueryClientProvider>
);
}
When I start dev environment,"Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported." displayed.
I use below languages. ・React ver18 ・Next.js ver14.1.0 ・TypeScript ver5
I'm beginner for coding.If you are hard to read code, I apologize.
I mented out the "useFetchData" file because I think there is cause in fetch process. But it doesn't improve anything...
Please help me.
Share Improve this question edited Mar 7, 2024 at 8:04 Youssouf Oumar 46.6k16 gold badges103 silver badges105 bronze badges asked Mar 7, 2024 at 0:43 NatsNats 431 silver badge3 bronze badges2 Answers
Reset to default 7Within the app
router, ponents are by default server ponents (Home
), and a server ponent can only pass a JSON serializable prop to client ponents (QueryClientProvider
).
Or that queryClient
you are passing to QueryClientProvider
from Home
is a plex object that contains functions and all. This is your problem.
You can add "use client"
at the top of Home
to make it a client ponent or, move the QueryClientContextProvider
in its own file, like so:
// QueryClientContextProvider.tsx
"use client";
import { ReactNode } from "react";
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
const queryClient = new QueryClient();
export default function QueryClientContextProvider({ children }: { children: ReactNode }) {
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}
import QueryClientContextProvider from "@/ponents/QueryClientContextProvider";
import PublishedMovieList from "./ponents/PublishedMovieList";
import Sidebar from "./ponents/Sidebar";
export default function Home() {
return (
<QueryClientContextProvider>
<main className="bg-indigo-950 min-h-screen min-w-full">
<div className="text-5xl py-10 pl-5 border-b border-white">
<h1>今日、何観る?</h1>
</div>
<div className="flex">
<div>
<Sidebar />
</div>
<div>
<PublishedMovieList />
</div>
</div>
</main>
</QueryClientContextProvider>
);
}
Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top This is why it is important to have the initial setup of tanstack react query in a separate file before importing it in the root layout.
https://tanstack./query/latest/docs/framework/react/guides/advanced-ssr