blitz-js / babel-plugin-superjson-next

Automatically transform your Next.js Pages to use SuperJSON
MIT License
125 stars 15 forks source link

Is InferGetStaticPropsType required to make superjson work with nextjs? #18

Closed marceloverdijk closed 3 years ago

marceloverdijk commented 3 years ago

Hi,

I'm wondering if InferGetStaticPropsType is required to make superjson work with nextjs? The example here https://github.com/blitz-js/babel-plugin-superjson-next/tree/main/example uses that way and that works for me, but changing the page a bit bit fails.

import type { InferGetStaticPropsType } from 'next';

export async function getStaticProps() {
  return {
    props: {
      date: new Date(0),
    },
  };
};

export default function Page(props: InferGetStaticPropsType<typeof getStaticProps>) {
  return 'props.date is Date: ' + (props.date instanceof Date);
}

it prints nicely: props.date is Date: true

But when changing it a bit to:

import type { GetStaticProps } from 'next';
import React from 'react';

type Props = {
  date: Date
}

export const getStaticProps: GetStaticProps<Props> = async () => {
  return {
    props: {
      date: new Date(0),
    },
  }
}

const Date2Page = ({ date }: Props): JSX.Element => (
  <div>
    <p>props.date is Date: {date instanceof Date}</p>
  </div>
)

export default Date2Page

it only prints: props.date is Date:

I changed it because I want to type the Props and use it in getStaticProps and Date2Page.

Skn0tt commented 3 years ago

No, using InferGetStaticPropsType shouldn't impact the result whatsoever - especially considering that type information isn't available at runtime.

What you describe is unexpected 🤔 Could you maybe provide a CodeSandbox reproducing the error? That'd allow me to play around with what's happening there.

marceloverdijk commented 3 years ago

Hi @Skn0tt , I created this example https://github.com/marceloverdijk/superjson-example

I've added a with-props.tsx page which contains:

import React from 'react';
import type { GetStaticProps, InferGetStaticPropsType } from 'next';

type Props = {
  date: Date
}

export const getStaticProps: GetStaticProps<Props> = async () => {
  return {
    props: {
      date: new Date(0),
    },
  }
}

const WihPropsPage = ({ date }: Props): JSX.Element => (
  <p>props.date is Date: {date instanceof Date}</p>
)

export default WihPropsPage

When accessing the page at http://localhost:3000/with-props I get:

props.date is Date:

instead of the expected:

props.date is Date: true

Skn0tt commented 3 years ago

Haha, found the mistake! :D

<p>props.date is Date: {date instanceof Date}</p> is not the same as 'props.date is Date: ' + (date instanceof Date) The first one uses JSX templating, the second one string concatenation. JSX templates don't render booleans (that'd break the classic { someCondition && (<p>This only shows up sometimes</p>) } trick).

So this can be fixed by changing the code to this:

<p>props.date is Date: {(date instanceof Date).toString()}</p>

Does that help? ☺️

marceloverdijk commented 3 years ago

Thx, yes that helps a lot! So it is just my lack of experience with React 🙈 .

Initially I was doing {date} and that was also giving an issue. As I know now dates are no valid render objects and I have to use {date.toString()}

Thx again!