Search code examples
reactjsnext.jstanstackreact-query

Error: Only plain objects, and a few builtins can be passed to Client Components from Server Components. Classes or null prototypes are not supported


I have created a simple react app to fetch data from an api. Basically it should only display the name of a material given from the api. When I call the api in the browser, it shows the JSON data correctly. Now when I reload my frontend page the following error message is displayed: Error: Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported. at stringify () at stringify ()

I created a file called "Material API". Here fetch the data from the API.

import axios, { AxiosResponse } from "axios";
import { Material } from "../model/Material";
import { toast } from "sonner";

import { QueryData } from "@/app/model/QueryData";
import error from "next/error";

const fetchMaterial = () => {
  return axios
    .get<Material[]>("http://127.0.0.1:8000/show-data/")
    .catch((e) => {
      console.error(e);
      toast.error("Error getting material");
      throw error;
    });
};

export const getMaterial = (): QueryData<Material[]> => ({
  queryKey: ["material"],
  queryFn: async () => {
    const response = await fetchMaterial();
    return response.data;
  },
});

The component "MaterialList" will display the data i get from the API.

"use client"

import { getMaterial } from "../api/MaterialApi";
import { useQuery } from "@tanstack/react-query";
import { Box, Skeleton, Typography } from "@mui/material";

interface MaterialListProps {}

export const MaterialList: React.FC<MaterialListProps> = () => {
  const { isLoading, data } = useQuery({
    ...getMaterial(),
    refetchOnMount: false,
    refetchOnWindowFocus: false,
  });

  return (
    <Box>
      {isLoading ? (
        <Skeleton sx={{ width: "100%" }} />
      ) : (
        <ul>
          {data?.map((material) => (
            <li key={material.id}>
              <Typography>{material.name}</Typography>
            </li>
          ))}
        </ul>
      )}
    </Box>
  );
};

I hope somebody can help me with this one.

Tried using an async method but still got the same error.


Solution

  • Try to add "use client" at the top of your MaterialApi file:

    "use client"
    
    import axios, { AxiosResponse } from "axios";
    import { Material } from "../model/Material";
    import { toast } from "sonner";
    
    import { QueryData } from "@/app/model/QueryData";
    import error from "next/error";
    
    const fetchMaterial = () => {
      return axios
        .get<Material[]>("http://127.0.0.1:8000/show-data/")
        .catch((e) => {
          console.error(e);
          toast.error("Error getting material");
          throw error;
        });
    };
    
    export const getMaterial = (): QueryData<Material[]> => ({
      queryKey: ["material"],
      queryFn: async () => {
        const response = await fetchMaterial();
        return response.data;
      },
    });
    

    The function getMaterial exported from the file is considered as server side function and when you import it in your client component the provided error appears.