Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type error when assigning extended NextPage type to a page component

I'm getting the type error on const Page as seen in the screenshot and code block below.

enter image description here

Type '{ (props: Props): JSX.Element; getLayout(page: ReactElement<any, string | JSXElementConstructor<any>>): JSX.Element; }' is not assignable to type 'NextPageWithLayout'.
  Type '{ (props: Props): JSX.Element; getLayout(page: ReactElement<any, string | JSXElementConstructor<any>>): JSX.Element; }' is not assignable to type 'FunctionComponent<{}> & { getInitialProps?(context: NextPageContext): {} | Promise<{}>; } & { getLayout?: ((page: ReactElement<any, string | JSXElementConstructor<...>>) => ReactNode) | undefined; }'.
    Type '{ (props: Props): JSX.Element; getLayout(page: ReactElement<any, string | JSXElementConstructor<any>>): JSX.Element; }' is not assignable to type 'FunctionComponent<{}>'.
      Types of parameters 'props' and 'props' are incompatible.
        Property 'pictures' is missing in type '{}' but required in type 'Props'.ts(2322)
galleryssr.tsx(19, 3): 'pictures' is declared here.

The error is saying that NextPageWithLayout is not accepting getLayout, but that was working fine before I introduced data fetching with getServerSideProps and passed props in as an argument.

I think I need to update getLayout or NextPageWithLayout somehow to accept props, but I can't figure out the syntax.

NextLayoutWithPage is defined in _app.tsx:

export type NextPageWithLayout = NextPage & {
  getLayout?: (page: ReactElement) => ReactNode;
};

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout;
};

function MyApp({ Component, pageProps }: AppPropsWithLayout) {
  const getLayout = Component.getLayout ?? ((page) => page);

  return (
      <ThemeContextProvider>
          {getLayout(<Component {...pageProps} />)}
      </ThemeContextProvider>
  );
}

export default MyApp;

galleryssr.tsx

import type { ReactElement } from "react";
import { SidebarLayout } from "../layouts/SidebarLayout";
import type { NextPageWithLayout } from "./_app";
import Image from "next/image";
import { GetServerSideProps } from "next";

type Picture = {
  id: string;
  author: string;
  width: number;
  height: number;
  url: string;
  download_url: string;
};

// Define type animals which is an array of objects
type Props = {
  pictures: Picture[];
};

const Page: NextPageWithLayout = (props: Props) => {
  return (
    <div className="w-full text-left">
      <h1>This is a server side rendered gallery</h1>
      <div className="grid grid-cols-1 grid-gap-4">
        {props.pictures.map((picture) => {
          return (
            <div
              className="flex flex-col items-center justify-center bg-base-200 p-4 rounded-md my-4"
              key={picture.id}
            >
              <div className="h-[300px] w-[300px] relative">
                <Image
                  src={picture.download_url}
                  alt={picture.id}
                  layout="fill"
                  objectFit="contain"
                  width={picture.width / 20}
                  height={picture.height / 20}
                />
              </div>

              <div>{picture.author}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

Page.getLayout = function getLayout(page: ReactElement) {
  return <SidebarLayout>{page}</SidebarLayout>;
};

// This gets called on every request
export const getServerSideProps: GetServerSideProps = async () => {
  // Fetch data from external API
  const res = await fetch(`https://picsum.photos/v2/list`);
  const pictures = await res.json();
  return { props: { pictures } };
};

export default Page;
like image 232
user12457151 Avatar asked Oct 21 '25 05:10

user12457151


1 Answers

In order to make NextPageWithLayout also accept the component's props type you can define an optional generic type that you'll pass down to NextPage.

export type NextPageWithLayout<P = {}> = NextPage<P> & {
    getLayout?: (page: ReactElement) => ReactNode;
};

You can now define your Page's type as follows:

type Props = {
    pictures: Picture[];
};

const Page: NextPageWithLayout<Props> = (props) => {
    // Your component's code
};
like image 66
juliomalves Avatar answered Oct 23 '25 20:10

juliomalves



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!