Exploring the benefits of using getServerSideProps with NextJS and Typescript for

Dear community, I am facing a challenge with integrating NextJS Layout and Typescript. Although everything seems to be working fine, I can't seem to get rid of the squiggly line under the props when passing them from getServerSideProps.

The prop {someText) always shows an annoying squiggle - you can check the screenshot for reference.

I understand that I cannot pass these props directly to the Layout itself, but according to my knowledge, I should be able to pass them to the page itself... and the code does function correctly!

I've spent quite some time trying to fix this issue... hoping someone in this forum can guide me in the right direction :)

For now, I am using {someText}:any as a workaround.

Here's the screenshot.

This is my next.d.ts file:

import type { NextPage } from 'next';
import NextComponentType from 'next/dist/shared/lib/utils'
import type { AppProps } from 'next/app';

declare module 'next' {
    type Page<P = {}, IP = P> = NextPage<P, IP> & {
        getLayout?: (Component: NextComponentType) => JSX.Element;
    }
}

declare module 'next/app' {
    type AppPropsWithLayout<P = {}> = AppProps<P> & {
        Component: Page;
    }
}

Below is what I have exported from _App.tsx (includes Recoil and MUI components):

// mui-app.tsx
import { RecoilRoot } from 'recoil'

import { useEffect, useState } from 'react';
import Head from 'next/head';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { CacheProvider, EmotionCache } from '@emotion/react';
import theme from './theme';
import createEmotionCache from './createEmotionCache';

import { SessionProvider } from 'next-auth/react';

import type { ReactNode} from 'react'
import { AppPropsWithLayout } from 'next/app';


interface MuiAppProps extends AppPropsWithLayout{
  emotionCache?: EmotionCache
}

// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();


export function MuiApp(props: MuiAppProps):JSX.Element {
  const { Component, emotionCache = clientSideEmotionCache, pageProps: { session, ...pageProps } } = props;
  const getLayout = Component.getLayout ?? ((page: ReactNode): ReactNode => page)
  const [mounted, setMounted] = useState(false)
  useEffect(() => {
    setMounted(true)
  }, [])
  return (
    <SessionProvider session={pageProps.session} refetchInterval={0}>
      <RecoilRoot>

        <CacheProvider value={emotionCache}>
          <Head>
            <meta name="viewport" content="initial-scale=1, width=device-width" />
          </Head>
          <ThemeProvider theme={theme}>
            <CssBaseline />
            <div style={{ visibility: mounted ? 'visible' : 'hidden' }}>
              {getLayout(<Component {...pageProps} />)}
            </div>
          </ThemeProvider>
        </CacheProvider>

      </RecoilRoot>
    </SessionProvider>
  )
}

This is my index.tsx file:

import React, { ReactNode } from "react";
import type { Page } from 'next'
import { PageLayout } from "@app/UI/MUI/components/layout/page-layout";

const page: Page<{ someText: string }> = ({ someText }) => {
    return (
        <div>{someText}</div>
    )
}
export default page
page.getLayout = (page: Page) => {
    return (
        <PageLayout>{page}</PageLayout>
    )
}


export const getServerSideProps = async () => {

    return ({ props: { someText: 'This is a test' } })

}

Answer №1

Make sure to update the page type to NextPage.
Additionally, remember to capitalize the component name and include the getServerSideProps function:

import React, { ReactNode } from 'react';
import type { NextPage } from 'next';
import { PageLayout } from '@app/UI/MUI/components/layout/page-layout';

const MainPage: NextPage<{ content: string }> = ({ content }) => {
  return <div>{content}</div>;
};

export default MainPage;

MainPage.getLayout = (page: NextPage) => {
  return <PageLayout>{page}</PageLayout>;
};

import { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async () => {
  return { props: { content: 'Testing123' } };
};

Answer №2

It's unclear why my previous method didn't work, so I decided to make some modifications...

I made changes and stopped using next.d.ts

   import { ReactNode, ReactElement } from 'react'
    import { NextPage } from 'next'
    import { AppProps } from 'next/app'
    import { CacheProvider, EmotionCache } from '@emotion/react';
    export type Page<P = {}, IP = P> = NextPage<P, IP> & {
        getLayout?: (page: ReactNode) => ReactNode;
    }
    
    export type AppPropsWithLayout<P> = AppProps<P> & {
        //emotionCache?: EmotionCache
        Component: Page<P>;

}

The updated version of my App.tsx file

// pages/_app.tsx
//TODO: move imports and Recoil Provider to _App.ts
import { RecoilRoot } from 'recoil'

import { useEffect, useState } from 'react';
import Head from 'next/head';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { CacheProvider, EmotionCache } from '@emotion/react';
import theme from './theme';
import createEmotionCache from './createEmotionCache';

import { SessionProvider } from 'next-auth/react';

import type { ReactNode } from 'react'

import { AppPropsWithLayout } from '@app/types/app-types'//TODO: shorten


type MuiAppProps<P = {}> = AppPropsWithLayout<P> & {
  emotionCache?: EmotionCache
}

// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();


export function MuiApp(props: MuiAppProps): JSX.Element {
  const { Component, emotionCache = clientSideEmotionCache, pageProps: { session, ...pageProps } } = props;
  const getLayout = Component.getLayout ?? ((page: ReactNode): ReactNode => page)
  const [mounted, setMounted] = useState(false)
  useEffect(() => {
    setMounted(true)
  }, [])
  return (
    <SessionProvider session={pageProps.session} refetchInterval={0}>
      <RecoilRoot>

        <CacheProvider value={emotionCache}>
          <Head>
            <meta name="viewport" content="initial-scale=1, width=device-width" />
          </Head>
          <ThemeProvider theme={theme}>
            {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
            <CssBaseline />
            <div style={{ visibility: mounted ? 'visible' : 'hidden' }}>
              {getLayout(<Component {...pageProps} />)}
            </div>
          </ThemeProvider>
        </CacheProvider>

      </RecoilRoot>
    </SessionProvider>
  )
}

Now let's look at my index.tsx file

import React, { ReactNode } from "react";
import type { Page } from 'next'
import { PageLayout } from "@app/UI/MUI/components/layout/page-layout";

const page: Page<{ someText: string }> = ({ someText }) => {
    return (
        <div>{someText}</div>
    )
}
export default page
page.getLayout = (page: Page) => {
    return (
        <PageLayout>{page}</PageLayout>
    )
}


export const getServerSideProps = async () => {

    return ({ props: { someText: 'This is a test' } })

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Delivery Guy: Error: JSON parsing issue on line 1 – Unexpected number detected

I am currently learning web development and experimenting with Postman to send a POST request to one of my application's APIs. The website I am building is based on the Next.JS framework. Below is the code for my API: import type { NextApiRequest, Ne ...

Troubleshooting: The issue of importing Angular 2 service in @NgModule

In my Angular 2 application, I have created an ExchangeService class that is decorated with @Injectable. This service is included in the main module of my application: @NgModule({ imports: [ BrowserModule, HttpModule, FormsModu ...

When using a Redux action type with an optional payload property, TypeScript may raise complaints within the reducer

In my react-ts project, I define the following redux action type: type DataItem = { id: string country: string population: number } type DataAction = { type: string, payload?: DataItem } I included an optional payload property because there are tim ...

Am I on track with this observation?

I am currently using the following service: getPosition(): Observable<Object> { return Observable.create(observer => { navigator.geolocation.watchPosition((pos: Position) => { observer.next(pos); observer.c ...

Why isn't my Next.js middleware working properly with TypeScript?

My issue arises from the fact that, despite following the documentation, the middleware in Next.js is not functioning as I anticipated. I experimented with what I thought was the simplest middleware possible. I expected that when navigating to /, a conso ...

When using the `const { }` syntax, which attribute is made accessible to the external

I am using the ngrx store as a reference by following this example: https://stackblitz.com/edit/angular-multiple-entities-in-same-state?file=src%2Fapp%2Fstate%2Freducers%2Fexample.reducer.ts Within the code in example.reducer.ts, there is this snippet: ...

What's the process for updating __N_SSG from true to false in Next.js?

Is there a way to dynamically change the pageProps inside the __N_SSG parameter from true to false or remove them altogether? I have multiple pages generated at build time, and currently, I manually change true to false. However, every time I rebuild, I ...

Encountering a Npm ERR! when deploying Angular 6 to Heroku due to missing Start script

I am experiencing an issue with my simple angular 6 app after deploying it to Heroku. When I check the logs using the command heroku logs, I encounter the following error: 2018-07-15T00:45:51.000000+00:00 app[api]: Build succeeded 2018-07-15T00:45:53.9012 ...

Using Material UI date picker with TypeScript: A Complete Guide

Well, I have to admit that I usually don't resort to putting 'any' as the type when I'm uncertain what to do, but right now, I'm starting to feel quite frustrated. I'm currently working with Material UI date picker in conjunct ...

What is the best way to define the typings path for tsify?

My TypeScript sources are located in the directory: src/game/ts The configuration file tsconfig.json can be found at: src/game/ts/tsconfig.json Additionally, the typings are stored in: src/game/ts/typings When running tsc with the command: tsc --p s ...

Troubleshooting asynchronous problems with rxjs chaining within ngrx effects

@Effect({ dispatch: false }) public setJwtDataParcoursPage = this.actions$.pipe( ofType(INIT_FORM_SUCCESS_ACTION), map((action: InitFormSuccessAction) => action.payload), withLatestFrom(this.store.select(this._apiHeadersSelector.getJwt) as Observa ...

Instructions on how to dynamically show specific text within a reusable component by utilizing React and JavaScript

My goal is to conditionally display text in a reusable component using React and JavaScript. I have a Bar component that I use in multiple other components. In one particular ParentComponent, the requirement is to show limit/total instead of percentage va ...

Exchanging user information amongst components within the following 13

My backend is built using NestJS and includes a login route that generates a JWT and sets an http-only cookie with the token. After successful login on my frontend, I receive the cookie indicating that the user is authenticated. However, I am facing a chal ...

An error occurred in Next.js with i18n: Warning - Text content mismatch. Server displays an empty string while the client shows "fr"

An error is encountered upon loading the application. The application initially loads at URL http://localhost:3000/. However, when switching to a different language, such as French, the URL changes to http://localhost:3000/fr. Subsequently, when switching ...

Tips for editing events in the "react-big-calendars" component

I am looking to implement a feature where users can click on events in a calendar and then edit either the dates or event titles. Can this functionality be achieved using "react-big-calendar"? If not, are there any other packages you can recommend? <Cal ...

Show a loading progress indicator with a percentage until Next/React completes loading

For my upcoming SPA project, I will be fetching a 3D map and data from an API. Is there a method to incorporate a loading banner that displays the current percentage of files, components, or data loaded before the application is completely loaded? I am in ...

No data found in req.query object in ExpressJS

When I use http.post to send data from Angular to NodeJS, the req.query always comes back empty for me. Here is my server.js setup: const express = require('express'); const cors = require('cors'); const bodyParser = require('body ...

SWR: Enhance user experience with real-time UI updates upon changing data

Is there a way to make the UI update instantly without waiting for SWR to sync with the database? I attempted to refer to the documentation, but even after following it, the UI does not update automatically (I have to switch back and forth in my browser t ...

Angular is used to call a function that captures a specific div and then waits for the capture to be completed before

I'm facing a challenge where I need to handle the capturing of a div using a method called capture() within another method. Take a look at the code snippet below: theimage; // declaring the variable callcapture() { // perform certain actions t ...

Fetching data from the server in NextJS based on user input

After assembling a Client and a Server component (using App Router), I was able to refresh the Server when the user interacts with it, triggering a route refresh by using: router.push(pathname) Although that worked well for refreshing the Server, now I ne ...