app_.getInitialProps with page getServersideProps #11183
Replies: 10 comments 16 replies
-
You can observe the following results printed in your browser developer console with the following code sample:
This causes me to believe that getServerSideProps simply takes the |
Beta Was this translation helpful? Give feedback.
-
I am also wondering this. My |
Beta Was this translation helpful? Give feedback.
-
@majelbstoat can u update the title to |
Beta Was this translation helpful? Give feedback.
-
The question isn't about _app.getServersideProps - support for which doesn't exist yet. There are other discussions about adding support for that. This is about the interaction between _app.getInitialProps and page.getServersideProps. |
Beta Was this translation helpful? Give feedback.
-
One thing I have noticed is that when using Not sure if this is intended behavior or not, but it seems that |
Beta Was this translation helpful? Give feedback.
-
I'm coming across this issue too.. And have been looking all over to find a way to have a custom app that calls app.getInitialProps & a page with getServerSide props. So to confirm, this is not possible? I have a use case that would require this. |
Beta Was this translation helpful? Give feedback.
-
For anyone coming across this, I have make a function
That way I can easily fetch some default props for every page. It would be better to have it live in the |
Beta Was this translation helpful? Give feedback.
-
Is there no easy way? I don't like hard code very much. |
Beta Was this translation helpful? Give feedback.
-
This is what I have so far. Trying to get implicit cross-function type retention like I do on the client (pushing the provided apolloState into returned props for client inference) _app.tsximport '@/styles/index.css';
import '@/styles/chrome-bug.css';
import 'keen-slider/keen-slider.min.css';
import App, {
AppContext,
AppInitialProps,
AppProps,
NextWebVitalsMetric
} from 'next/app';
import { useRouter } from 'next/router';
import { ApolloProvider } from '@apollo/client';
import { useEffect, FC } from 'react';
import {
useApollo,
initializeApollo,
addApolloState
} from '@/lib/apollo';
import * as gtag from '@/lib/analytics';
import { MediaContextProvider } from '@/lib/artsy-fresnel';
import { Head } from '@/components/Head';
import { GTagPageview } from '@/types/analytics';
// import { AppLayout } from '@/components/Layout';
import {
GetInitialPropsResult,
InferGetInitialPropsType
} from '@/types/next-abstracted';
import {
DynamicNavQuery,
DynamicNavQueryVariables,
DynamicNavDocument,
WordpressMenuNodeIdTypeEnum
} from '@/graphql/generated/graphql';
const Noop: FC = ({ children }) => <>{children}</>;
function NextApp({
Component,
pageProps: { ...pageProps },
}: AppProps &
InferGetInitialPropsType<typeof NextApp.getInitialProps>) {
const apolloClient = useApollo(pageProps);
const LayoutNoop = (Component as any).LayoutNoop || Noop;
const router = useRouter();
useEffect(() => {
document.body.classList?.remove('loading');
}, []);
useEffect(() => {
const handleRouteChange = (url: GTagPageview) => {
gtag.pageview(url);
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return (
<>
<Head />
<ApolloProvider client={apolloClient}>
<MediaContextProvider>
<LayoutNoop pageProps={pageProps}>
<Component {...pageProps} />
</LayoutNoop>
</MediaContextProvider>
</ApolloProvider>
</>
);
}
NextApp.getInitialProps = async (
appContext: AppContext
): Promise<
GetInitialPropsResult<{
pageProps: AppInitialProps;
Header: DynamicNavQuery['Header'];
Footer: DynamicNavQuery['Footer'];
}>
> => {
const pageProps = await App.getInitialProps(appContext);
const graphqlClient = initializeApollo();
const dynamicNav = await graphqlClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idTypeHead: WordpressMenuNodeIdTypeEnum.NAME,
idTypeFoot: WordpressMenuNodeIdTypeEnum.NAME,
idFoot: 'Footer'
}
});
return addApolloState(graphqlClient, {
pageProps: {
...pageProps.pageProps,
Header: dynamicNav.data.Header,
Footer: dynamicNav.data.Footer
}
});
};
export function reportWebVitals(metric: NextWebVitalsMetric) {
console.debug('vital: ', metric);
}
export default NextApp; index.tsx (for comparison, this does provide 100% cross-function types on InferGetmethodPropsType)import { Container, LandingHero } from '@/components/UI';
import { initializeApollo, addApolloState } from '@/lib/apollo';
import { ServicesTopCoalesced } from '@/components/ServicesTop';
import { AppLayout } from '@/components/Layout';
import {
GetStaticPropsContext,
GetStaticPropsResult,
InferGetStaticPropsType
} from 'next';
import {
ServicesTopQuery,
ServicesTopQueryVariables,
ServicesTopDocument,
DynamicNavDocument,
DynamicNavQueryVariables,
DynamicNavQuery,
WordpressMenuNodeIdTypeEnum
} from '@/graphql/generated/graphql';
export function Index({
other,
popular,
Header,
Footer
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<>
<AppLayout
title={'✂ The Fade Room Inc. ✂'}
Header={Header}
Footer={Footer}
hero={<LandingHero />}
>
<Container clean className='fit'>
<ServicesTopCoalesced other={other} popular={popular} />
</Container>
</AppLayout>
</>
);
}
export async function getStaticProps(
ctx: GetStaticPropsContext
): Promise<
GetStaticPropsResult<{
other: ServicesTopQuery['other'];
popular: ServicesTopQuery['popular'];
Header: DynamicNavQuery['Header'];
Footer: DynamicNavQuery['Footer'];
}>
> {
const apolloClient = initializeApollo();
await apolloClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idTypeHead: WordpressMenuNodeIdTypeEnum.NAME,
idTypeFoot: WordpressMenuNodeIdTypeEnum.NAME,
idFoot: 'Footer'
}
});
await apolloClient.query<
ServicesTopQuery,
ServicesTopQueryVariables
>({
query: ServicesTopDocument,
variables: {
other: 'all',
popular: 'popular-service'
}
});
return addApolloState(apolloClient, {
props: {},
revalidate: 10
});
}
export default Index; I'd like to move AppLayout into App with 100% strongly typed props passed from NextApp.getInitialProps to the default NextApp function being exported. Is there a way to explicitly state the Return props expected as a promise like you can with GetStaticPropsResult and GetServerSidePropsResult? Update: Now my Component is typed as follows: var Component: NextComponentType<NextPageContext, any, (appContext: AppContext) => Promise<GetInitialPropsResult<{
pageProps: AppInitialProps;
Header: Maybe<{
__typename?: "WordpressRootQuery" | undefined;
} & {
...;
}>;
Footer: Maybe<...>;
}>>> Note: I am trying to write my own GetInitialPropsResult and InferGetInitialPropsType definitions...kind of works at the moment but feedback would be greatly appreciated types/next-abstracted.tsimport App, {
AppInitialProps,
AppProps,
AppContext
} from 'next/app';
import { Component } from 'react';
export declare function getNextAppInitialProps({
Component,
ctx
}: AppContext): Promise<AppInitialProps>;
export type GetInitialPropsResult<P> = {
pageProps: P | AppInitialProps;
};
export type InferGetInitialPropsType<T> = T extends App<
infer P,
AppInitialProps,
any
>
? P
: T extends (
context?: AppContext
) => Promise<GetInitialPropsResult<infer P | AppProps<T>>>
? P
: Component; |
Beta Was this translation helpful? Give feedback.
-
send props to _app with
|
Beta Was this translation helpful? Give feedback.
-
I know that
_app.getServersideProps
doesn't exist yet, but is there a way to get_app.getInitialProps
to correctly pass props to theApp
if a page definesgetServersideProps
? Simple illustration:This prints
viewer { id: 'monkey' }
as expected. However, if I add getServersideProps to IndexPage:It now prints
viewer undefined
I presume the result of
getServersideProps
is being used as the page props, but I don't understand the order in which things execute, and/or whether something like this is possible. I don't want to usegetInitialProps
on the page, becausegetServersideProps
does exactly what I want in terms of direct db access etc. (Nice capability upgrade, thank you!)What I'm trying to achieve:
Beta Was this translation helpful? Give feedback.
All reactions