Why so00 DYNAMIC?
Tags: react, javascript, nextjs, webdev
Published: 2021-06-09 09:35:24

Hello everyone! Hope you are reacting well. So, this is my first post in dev.to and I thought to start with a Next.Js blog. So today let's discuss how to work in dynamic pages using getStaticProps and getStaticPath.

In Next.Js not like in react, they provide us file based routing and you can see those pages under pages folder. In there you can create new files with .js extension and make sure you have named it with the route you needed. (eg : if you want to have an about page you have to name that page as about.js and for '/' path you must name it as index.js). Also you can define dynamic URLs with as follows and make sure you have defined the parameter inside square brackets.

eg : [blogId].js

To access that parameter inside the dynamic URL, we can use useRouter hook which is imported from next/router. Then you can grab the parameter values as follows. But this is not the way we are going to follow today.


```javascript
//in [blogId].js file
import {Router} from 'next/router'

const MyPage => () => {
    const router = useRouter()
    return(
        <h1>{router.query.blogId}</h1>
    )
}

export default MyPage
```
When it comes to data fetching, if we do data fetching in Next.Js as we do in react components with useEffect, that fetched content do not affect SEO because the page is hydrated from data after it pre-renders and therefor server won't be able to see that fetched data. There for we can use built in functions called as getStaticProps and getServerSideProps to fix that issue. Today I'm going to focus on getStaticProps function which is the most preferred way to do this task.

```javascript
//in [blogId].js file
import {Router} from 'next/router'

const MyPage => (props) => {
    return(
        props.map(article => {
               return <h1>{article.title}</h1>
        })
    )
}

export async function getStaticProps(){
    const url = ""
    const response = await fetch(url)
    const data = await response.json()
    return{
        props:data
    }
}

export default MyPage
```
As you can see in the above getStatic Props async function after the data is fetched we have to return that data inside an object with the key props so that page component will be able to access that data via props.

Also, in the above page it show only data fetched for the first time to the server. There for even if changd the data in our backend API data in the component does not change. Therefor to fix that issue we can put a revalidate time out inside the returned object with revalidate key as follows.

```javascript
//in [blogId].js file
import {Router} from 'next/router'

const MyPage => (props) => {
    return(
        props.map(article => {
               return <h1>{article.title}</h1>
        })
    )
}

export async function getStaticProps(){
    const url = ""
    const response = await fetch(url)
    const data = await response.json()
    return{
        props:data,
        revalidate:1, //this revalidates in every second
    }
}

export default MyPage
```

Then how can we access the url parameters? That's simple. You can pass an argument to the function called as context. Context is a nested object. From that, you can access url parameters as follows.

```javascript
//in [blogId].js file
import {Router} from 'next/router'

const MyPage => (props) => {
    return(
        props.map(article => {
               return <h1>{article.title}</h1>
        })
    )
}

export async function getStaticProps(context){

    const blogId = context.params.blogId /*blogId is the name of 
    parameter*/

    const url = ""
    const response = await fetch(url)
    const data = await response.json()
    return{
        props:data
        revalidate:1, //this revalidates in every second
    }
}

export default MyPage
```
If you run the dev server with npm run dev with above setup you will get an array saying about getStaticPath. Now let's see how we can fix that issue.

So to fix that issue you have to call a built in next.js function called getStaticPath inside your page and return an object with two keys, fallback (boolean) and paths (array) as follows. 
```javascript
//in [blogId].js file
import {Router} from 'next/router'

const MyPage => (props) => {
    return(
        props.map(article => {
               return <h1>{article.title}</h1>
        })
    )
}

export async function getStaticPath(){
    return{
        fallback:true,
        paths:[]
    }
}

export async function getStaticProps(context){

    const blogId = context.params.blogId /*blogId is the name of 
    parameter*/

    const url = ""
    const response = await fetch(url)
    const data = await response.json()
    return{
        props:data
        revalidate:1, //this revalidates in every second
    }
}
export default MyPage
```
So in the above paths array you can define all the possible parameter values so that if user enters a different value than those defined ones, he/she will be redirected to a 404 page. Also, you can set fallback to false when you are in develop server and make sure you have set it true or "blocking" when you deploy your app.

```javascript
//in [blogId].js file
import {Router} from 'next/router'

const MyPage => (props) => {
    return(
        <h1>{props.title}</h1>
    )
}

export async function getStaticPath(){
    const url = ""
    const response = await fetch(url)
    const data = await response.json()
    return{
        fallback:true,
        paths:data.map(item => {return{param:{blogId:item.id}}})
    }
}

export async function getStaticProps(context){

    const blogId = context.params.blogId /*blogId is the name of 
    parameter*/

    const url = ""
    const response = await fetch(url)
    const data = await response.json()
    const article = data.find((article) => article.id === blogId )
    return{
        props:article
        revalidate:1, //this revalidates in every second
    }
}
export default MyPage
```
Refer the above code snippet for the complete process.
Github Link for a same sort of project : https://github.com/shakyapeiris/meetup_web.git
So that's it! Thanks You!