Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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. #4517

Open
3 tasks done
ZynthCode opened this issue May 3, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@ZynthCode
Copy link

ZynthCode commented May 3, 2024

Describe the issue that you're seeing. Any Loom videos or screenshots usually help a lot!

When I am transitioning from using import client from "../../tina/__generated__/client"; to import client from "../../tina/__generated__/databaseClient"; objects that were previously successfully serializable are no longer serializable.

For example, using the client this worked:

const result = await client.queries.home({ relativePath: `home.mdx` });
return <HomeContent {...result} />;

With HomeContent looking like this:

const HomeContent = (props: {data: HomeQuery, variables: HomeQueryVariables, query: string}) => {
  const { data } = useTina(props);
  const home = data.home as Home;

  return (
    <div data-tina-field={tinaField(home)} className="py-12 space-y-12 ">
      <TitleSection {...home} />
      <HomeSections {...home} />
    </div>
  );
};

This no longer works after changing client to databaseClient. The reasons for this is unknown, but I suspect under the hood the way TinaCMS handles typing is different somehow. Would be excellent if we could find a way to use Tina's generated types to solve this, without having to manually parse the data everywhere we ask for a result from Tina.

The temporary solution

const rawResult = await client.queries.home({ relativePath: `home.mdx` });
const result = {
  data: {
    home: {
      title: rawResult.data.home.title
    }
  },
  variables: rawResult.variables,
  query: rawResult.query
};

return <HomeContent {...result} />;
export type HomeContentProps = {
  data: {
    home: {
      title: string;
    };
  };
  variables: any;
  query: string;
};

const HomeContent = (props: HomeContentProps) => {
  const { data } = useTina(props);
  const home = data.home as Home;

  return (
    <div data-tina-field={tinaField(home)} className="py-12 space-y-12 ">
      <TitleSection {...home} />
      <HomeSections {...home} />
    </div>
  );
};

Not a good way to handle this, since I would have to manually change multiple places, and remember to change it. More overhead.

Reproduction

https://github.com/ZynthCode/tina-nextjs-app

Steps to reproduce

git clone https://github.com/ZynthCode/tina-nextjs-app

Navigate to /src/app/page.tsx and change getHomeProps() to use the rawData directly from const rawData = await client.queries.post({ relativePath: "_home.md" });, rather than using the hacky a DTO to transfer data.

Jump into <HomeContent {...props} /> and replace the props with what we normally would use (using generated types):

(props: {data: PostQuery, variables: PostQueryVariables, query: string}) => {

Install and run the app:

yarn
yarn dev

Navigate to localhost:3000 and you will see error logs:

 ⨯ 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.

This does not occur when you use the client and TINA_PUBLIC_IS_LOCAL=true.

System Info

Need to install the following packages:
envinfo@7.13.0
Ok to proceed? (y) y

  System:
    OS: Linux 6.5 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900H
    Memory: 45.93 GB / 62.43 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
  Binaries:
    Node: 18.19.0 - ~/.nvm/versions/node/v18.19.0/bin/node
    Yarn: 1.22.22 - ~/dev/zynthcode/tina-nextjs-app/node_modules/.bin/yarn
    npm: 10.2.3 - ~/.nvm/versions/node/v18.19.0/bin/npm
  Browsers:
    Brave Browser: 124.1.65.126
    Chrome: 121.0.6167.160
  npmPackages:
    @tinacms/cli: ^1.5.43 => 1.5.43 
    @tinacms/datalayer: ^1.2.33 => 1.2.33 
    tinacms: ^1.6.1 => 1.6.1

(Same issue in tinacms 1.6.2 btw)

Validations

@ZynthCode ZynthCode added the bug Something isn't working label May 3, 2024
@ZynthCode
Copy link
Author

The fix would be to change (or add) generated types that are compatible with serialization from backend to frontend components.

@ZynthCode
Copy link
Author

ZynthCode commented May 8, 2024

I have discovered a better hack that allows you to keep using the data types generated.

Create an util function:

export const fixTinaResults = <T>(data: T): T => {
  try {
    const serializedData = JSON.stringify(data);
    return JSON.parse(serializedData) as T;
  } catch (error) {
    console.error("Error in serializing/deserializing data:", error);
    throw new Error("Handling data failed");
  }
};

Then use it like this:

const rawResult = await client.queries.layout({ relativePath: "layout.mdx" });
const result = fixTinaResults(rawResult);

You don't have to change anything else, it should work as-as. 🤷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant