# Page Router

## Pre-rendering

* Traditionally, we use useEffect to fetch the data to update the ui. However, useEffect is triggered after the initial functional component is rendered
* Therefore, we cannot see the data from the source, which is not good for search engine optimization, so that we need pre-rendering

![](/files/-M_npNM8Tr6lBPZwwY42)

NextJS can do pre-rendering , which have 2 types - static generation and server-rendering

### Static Site Generation

#### GetStaticProps

* &#x20;The html file with initial data will be generated during build time, so that in every user request, the initial content of web page will be the same

```javascript
// Functional Component
const Home = (props) => {
    return ...
}

// Static Generation
// The method name must be getStaticProps
// the object including props must be returned 
// and pass it to the functional component
export const getStaticProps = async () => {
  try {
    const { homeData } = await  import("../data/home.js");
    return {
      props: { homeData, error: "hi" },
    };
  } catch (error) {
    return {
      props: { error: error.message },
    };
  }
};
```

![The building process](/files/-M_nqyzL13uQEQxTgJa2)

* If we want to generate the page in every couple of time in order to keep the data of pre-rendering updated

```javascript
export const getStaticProps: GetStaticProps = async () => {
  try {
    const { homeData } = await import("../data/home.js");
    return {
      props: { homeData, error: "hi" },
      // the page will be re-generated in every 10 seconds
      revalidate : 10
    };
  } catch (error) {
    return {
      props: { error: error.message },
      revalidate : 10
    };
  }
};
```

#### GetStaticPath

* For the dynamic page, such as \[id].js, nextjs need to knows which id should pre-render
* If the id doesn't included, 404 default error page will be returned if setting fallback is false&#x20;

```javascript
// Functional Component
const Detail = () =>{
    ...
}

// Pass the path that include based on the data file
// The object including path which containg params object must be returned
export const getStaticPaths = async () => {
  try {
    const { projectList } = await import("../../data/project");
    const pathList = projectList.map(({ id }) => ({
      params: {
        projectId: id,
      },
    }));
    return {
      fallback: false,
      paths: pathList,
    };
  } catch (err) {
    return {
      fallback: true,
      paths: [],
    };
  }
};

// Get back the object from getStaticPath by context
// Then generate the corresponding data based on the param in the build time
export const getStaticProps = async (context) => {
  const { projectId } = context.params;
  try {
    const { data } = await import(`../../data/${projectId}`);
    return {
      props: { data },
    };
  } catch (err) {
    return {
      props: { error: err.message },
    };
  }
};

export default Detail;
```

* fallback can also set to be blocking

```javascript
import React from 'react';
import {useRouter} from "next/router";
const Test = () => {
    const route = useRouter();
    return (
        <div>
            {route.query.id}
        </div>
    )
}

export const getStaticPaths = () => {
    const pathList = ['1','2'].map(item=> ({params:{id: item}}))
    console.log(pathList);
    return  {
        fallback: "blocking",
        paths: pathList
    }
}
export const getStaticProps = (context) => {
    return {props:{}};
}
export default Test

```

* Apart from 1 and 2, other id will be rendered on the server before showing the page, after rendering, the new page will be cache
* fallback can also to be true

```javascript
import React from 'react';
import {useRouter} from "next/router";
const Test = () => {
    const route = useRouter();
    if (route.isFallback) {
        return <div>Loading...</div>
      }
    return (
        <div>
            {route.query.id}
        </div>
    )
}

export const getStaticPaths = () => {
    const pathList = ['1','2'].map(item=> ({params:{id: item}}))
    return  {
        fallback: true,
        paths: pathList
    }
}
export const getStaticProps = (context) => {
    return {props:{}};
}
export default Test
```

* Initially, the loading page will be shown, meanwhile, the relevant html and json will be generated on the background and then render the page. After finished, the page will be changed into full page

### Server Side Rendering

* The page will be rendered on the server for each user request, and request and response of the page can obtained through context

```javascript
import React from 'react'

const servertest = () => {
    return (
        <div>
            getServerSideProps
        </div>
    )
}

export const getServerSideProps = (context) => {
    // ...
    console.log(context.req, context.res);
    if(notFound)
        return {
            notFound: true
        }
    if(!auth){
        return {
            redirect: {
              destination: '/',
              permanent: false,
            },
         }
    }
    
    return {
        props:{}
    }
      

}

export default servertest
```

* Request obtained can be used to determined whether the user can be authenticated to enter the page  or not

```javascript
import withSession from '../lib/session'
import Layout from '../components/Layout'

export const getServerSideProps = withSession(async function ({ req, res }) {
  // Get the user's session based on the request
  const user = req.session.get('user')

  if (!user) {
    return {
      redirect: {
        destination: '/login',
        permanent: false,
      },
    }
  }

  return {
    props: { user },
  }
})

const Profile = ({ user }) => {
  // Show the user. No loading state is required
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile
```

## SWR

* used for client-side rendering
* Here is the simple example with nextjs pre-rendering

```javascript
  const Page = ({data:preRenderData}) => {
    const fetcher = (url: string) => axios.get(url).then((res) => res.data);
    const { data, error } = useSWR<Page>(
      `${process.env.REACT_API_URL}/sample-page`,
      fetcher,
      { initialData: preRenderData }
    );
  
    if (!data && !error) return <span>Loading...</span>;
    
    // render page...
  }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://petercheng7788.gitbook.io/developer-note/frontend/react/nextjs/page-router.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
