Next.js Tutorial - Part 8 - Static Site Generation getStaticProps and getStaticPaths currentPage 3
https://github.com/mui-org/material-ui/tree/master/examples/nextjs/pages
get currentPage
C:\Users\Administrator\Desktop\abc\pages\_app.js
import AppBar from '@material-ui/core/AppBar';
import Box from '@material-ui/core/Box';
import Container from '@material-ui/core/Container';
import CssBaseline from '@material-ui/core/CssBaseline';
import IconButton from '@material-ui/core/IconButton';
import { ThemeProvider } from '@material-ui/core/styles';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import MenuIcon from '@material-ui/icons/Menu';
import App from 'next/app';
import Head from 'next/head';
import React from 'react';
import theme from '../theme';
export default class MyApp extends App {
componentDidMount() {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}
render() {
const { Component, pageProps } = this.props;
return (
<React.Fragment>
<Head>
<title>My page</title>
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
</Head>
<AppBar position="fixed">
<Toolbar variant="dense">
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6">Microphone Shop</Typography>
</Toolbar>
</AppBar>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Container>
<Box marginTop={8}>
<Component {...pageProps} />
</Box>
</Container>
</ThemeProvider>
</React.Fragment>
);
}
}
C:\Users\Administrator\Desktop\abc\pages\_document.js
import { ServerStyleSheets } from '@material-ui/core/styles';
import Document, { Html, Head, Main, NextScript } from 'next/document'
import React from 'react';
import theme from '../theme';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
MyDocument.getInitialProps = async ctx => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
C:\Users\Administrator\Desktop\abc\pages\index.tsx
import { Grid } from '@material-ui/core';
import Card from '@material-ui/core/Card';
import CardActionArea from '@material-ui/core/CardActionArea';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Typography from '@material-ui/core/Typography';
import { GetStaticProps } from 'next';
import Link from 'next/link';
import { Microphone } from '../../model/Microphone';
import openDB from '../openDB';
export interface IndexProps {
microphones: Microphone[];
}
export default function Index({ microphones }: IndexProps) {
return (
<Grid container spacing={3}>
{microphones.map((microphone) => (
<Grid item xs={12} sm={3} key={microphone.id}>
<Link href="/microphone/[id]" as={`/microphone/${microphone.id}`}>
<a>
<Card>
<CardActionArea>
<CardMedia
component="img"
alt={microphone.brand + ' ' + microphone.model}
height="300"
image={microphone.imageUrl}
title={microphone.brand + ' ' + microphone.model}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{microphone.brand + ' ' + microphone.model}
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="p"
>
Lizards are a widespread group of squamate reptiles, with
over 6,000 species, ranging across all continents except
Antarctica
</Typography>
</CardContent>
</CardActionArea>
</Card>
</a>
</Link>
</Grid>
))}
</Grid>
);
}
export const getStaticProps: GetStaticProps = async (ctx) => {
console.log(ctx);
const currentPage = ctx.params?.currentPage as string;
const currentPageNumber = +(currentPage || 0);
const min = currentPageNumber * 5;
const max = (currentPageNumber + 1) * 5;
const db = await openDB();
const microphones = await db.all(
'select * from microphone where id > ? and id <= ?',
min,
max
);
return { props: { microphones } };
};
C:\Users\Administrator\Desktop\abc\pages[currentPage].tsx
import { GetStaticPaths } from 'next';
import openDB from '../openDB';
import Index, { getStaticProps } from './';
export default Index;
export { getStaticProps };
export const getStaticPaths: GetStaticPaths = async () => {
const db = await openDB();
const { total } = await db.get('select count(*) as total from microphone');
const numberOfPages = Math.ceil(total / 5.0);
const paths = Array(numberOfPages- 1).fill('').map((_, index) => {
return { params: {currentPage: (index + 1).toString()}}
})
return {
fallback: false,
paths: paths,
};
};
Thư viện
Cách phân trang khá độc lạ
pages\index.tsx
import type { GetStaticProps, NextPage } from 'next';
import openDB from '../pages/openDB';
import {Microphone} from './model/Microphone';
export interface IndexProps {
microphones: Microphone[]
}
import styles from '../styles/Home.module.css'
import Link from 'next/link';
const Home: any = ({microphones}: IndexProps) => {
return (
<div className={styles.container}>
<main className={styles.main}>
{
microphones?.map((microphone) => {
return (
<Link className='block' href="/microphone/[id]" as={`/microphone/${microphone.id}`} key={microphone.id}>
{microphone.brand + " " + microphone.model + " " + microphone.price}
</Link>
)
})
}
</main>
</div>
)
}
export default Home
export const getStaticProps: GetStaticProps = async (ctx) => {
const currentPage = ctx.params?.currentPage as string;
const currentPageNumber = +(currentPage || 0);
const min = currentPageNumber * 5;
const max = (currentPageNumber + 1) * 5;
const db = await openDB();
const microphones = await db.all(
'select * from microphone where id > ? and id <= ?',min,max
);
return { props: { microphones } };
};
pages[currentPage].tsx
import { GetStaticPaths } from 'next';
import openDB from '../pages/openDB';
import Index, { getStaticProps } from './';
export default Index;
export { getStaticProps };
export const getStaticPaths: GetStaticPaths = async () => {
const db = await openDB();
const { total } = await db.get('select count(*) as total from microphone');
const numberOfPages = Math.ceil(total / 5.0);
const paths = Array(numberOfPages - 1).fill('').map((_, index) => {
return {
params: {
currentPage: (index + 1).toString()
}
}
});
return {
fallback: false,
paths: paths,
};
}
Page 0
Page 1
PreviousCách phân trang khá độc lạ xem bài Part 8 bên dưới 👇Next😍 Resolution order, On the server, On the server with error, On the client (ok)
Last updated
Was this helpful?