Creating A Page
We use the same convention as Next.js to create a page: all page components live inside the pages/ directory.
Make sure you place your pages inside directories with the correct domain prefix. For example, if you want to create a page for the /flight/search URL, you will create search.tsx inside the pages/flight directory.
'- packages/
'- flight/
'- app-desktop/
|- index.ts
'- pages/
|- _app.tsx
|- _document.tsx
'- flight/
'- search.tsx
Pages with dynamic route
Following Next.js standard, you can use the square-bracket syntax in your route to match dynamic path segments. For example, you can use
[param]to match one path segment — E.g.pages/activities/[country]/detail/[nameId].tsxwill match/activities/<something>/detail/<something>[...params]to match any number of path segments — E.g.pages/hotel/[...seoPath].tsxwill match/hotel/indonesia,/hotel/indonesia/jawa-barat, or anything under/hotel
Note that Next.js has priorities to deal with routing conflicts. Refer to the Next.js documentation for more information on this.
Types of page
You can access these examples at packages/sample/app-desktop/pages/sample/data-fetching.
Next.js gives options on how we can render our page, depending on what data fetching function you export from your page, e.g. getStaticProps or getServerSideProps. From our perspective, we categorize them as follows.
SSR (server-side rendered)
Also GSSP (getServerSideProps) pages. The page is rendered every time by your service every time it is visited (unless you manually set the Cache-Control response header).
const SampleGSSPPage: TravelokaPageComponent<any> = (props: any) => {
const { contentResource: cr } = useResource(SampleGSSPPageRQ);
const currency = useCurrency();
return (
<View style={styles.root}>
<VStack spacing="s">
{/* Test CR */}
<Card style={styles.card}>
<Text variant="title-1">{cr.FrontPage.pageTitle}</Text>
<Text>{cr.FrontPage.pageDescription}</Text>
</Card>
{/* Test props */}
<Card style={styles.card}>
<Text>{JSON.stringify(props)}</Text>
</Card>
</VStack>
</View>
);
};
export default SampleGSSPPage;
export const getServerSideProps: GetServerSideProps = async ctx => {
// You'll normally use `nextCtx` (instead of `ctx`) to call API
// const nextCtx = serverSideContextToNextContext(ctx);
const resourceQuery = mergeResource(SampleGSSPPageRQ);
const sharedPageProps = await getSharedServerProps(ctx, resourceQuery);
// Return props
return {
props: {
hello: 123,
...sharedPageProps,
},
};
};
SSG (static site generation)
Also called GSP (getStaticProps) pages. Normally, Next.js will render them during build, but we discard these renders during build and force Next.js to render the page on demand when it is live on staging/production. This way, we can build only once and serve different results on staging/production.
Note that you can pass the revalidate property to control how long we want to cache the page before attempting to render a newr version of the page.
const SampleGSPPage: TravelokaPageComponent<any> = (props: any) => {
const { contentResource: cr } = useResource(SampleGSPPageRQ);
return (
<View style={styles.root}>
<VStack spacing="s">
{/* Test CR */}
<Card style={styles.card}>
<Text variant="title-1">{cr.FrontPage.pageTitle}</Text>
<Text>{cr.FrontPage.pageDescription}</Text>
</Card>
{/* Test props */}
<Card style={styles.card}>
<Text>{JSON.stringify(props)}</Text>
</Card>
</VStack>
</View>
);
};
export default SampleGSPPage;
export const getStaticProps = staticProps({
path: `/sample/data-fetching/gsp`,
resources: [SampleGSPPageRQ],
getStaticProps: async (ctx: any) => {
return {
props: {
hello: 123,
},
revalidate: 10 * 60,
};
},
});
CSP (cacheable server props)
This behaves like GSSP (getServerSideProps), but the ctx you receive does not have user/view-specific data, so the page that you render would be cacheable.
const SampleGCSPPage: TravelokaPageComponent<any> = (props: any) => {
const { contentResource: cr } = useResource(SampleGCSPPageRQ);
return (
<View style={styles.root}>
<VStack spacing="s">
{/* Test CR */}
<Card style={styles.card}>
<Text variant="title-1">{cr.FrontPage.pageTitle}</Text>
<Text>{cr.FrontPage.pageDescription}</Text>
</Card>
{/* Test props */}
<Card style={styles.card}>
<Text>{JSON.stringify(props)}</Text>
</Card>
</VStack>
</View>
);
};
export default SampleGCSPPage;
export const getServerSideProps = cacheableServerProps({
resources: [SampleGCSPPageRQ],
getStaticProps: async ctx => {
// See `extractViewCacheKey` to see what values are available for `viewCacheKey`
// Try visiting: http://localhost:2900/en-sg/sample/data-fetching/gcsp?currency=IDR
const { viewCacheKey } = ctx;
return {
props: { hello: 123, viewCacheKey },
revalidate: 10 * 60,
};
},
});
GetInitialProps (deprecated)
This was a relic from the past, since when we first adopted Next.js, getInitialProps was the only data-fetching function that existed.
You should not create a new page with this data-fetching function.