What is getStaticProps() in Nextjs and How Does It Work?

Posted by Ashutosh on April 16, 2021





Next.js has an advantage over React apps on page pre-rendering. Please visit this link if you don't know server-side rendering.


In Next.js, we pre-rendered a page during build time. What does it mean? It means we generate all the HTML code and data in advance. And the data later cached by the server.


Does Next.js do it automatically? The short answer is No. We need to narrate Next.js to pre-generate the page during the build time.


Here getStaticProps comes into the picture. 


What is getStaticProps?


The getStaticProps is an async function that we need to export inside the page component. 


In this function, we can write any code (backend) that runs on the backend server. Sounds Interesting? Here is another benefit, the code that we write inside this function is not visible to the client. In short, if we need to connect with the database, we can do it inside this function and, our database credentials are not visible to the client.


Implementation


Let's create a new Next app and then create a new file lists.js under the pages folder. And update the following code in it.


function ListPageComponent(props) {
    return (
        <div>
            <h1>List of Folders</h1>
            <ul>
                {props.lists.map(list => <li key={list.dirId}>{list.name}</li>)}
            </ul>
        </div>
    )
}
export async function getStaticProps() {
    return {
        props: {
            lists: [
                {dirId: '1', name: 'Directory 1'},
                {dirId: '2', name: 'Directory 2'},
                {dirId: '3', name: 'Directory 3'},
                {dirId: '4', name: 'Directory 4'}
            ],
        }
    }
}
export default ListPageComponent;


Visit localhost:3000/lists and, you will see the list of directories. 


How does it work?

Whenever the page client loads the page, code inside getStaticProps executed first and, then it returns the object to the main page component. 


Remember, getStaticProps always return the object and, it executes before the page component.


We have implemented the getStaticProps function. So far, we didn't implement it in a way that can't be done on the client-side. 


Let's say we have to list all the directories under the /opt folder. Listing of directories cannot be done on the client. Let's achieve using the getStaticProps function. 


Create a new file next. config.js in the root of the application and update the following


module.exports = {
    webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
        config.node = {
            fs: 'empty', // This is required
        }
        return config
    }
}


And Update your lists.js page with the following code:


import fs from 'fs'
function ListPageComponent(props) {
    return (
        <div>
            <h1>List of Folders</h1>
            <ul>
                {props.lists.map(list => <li key={list.dirId}>{list.name}</li>)}
            </ul>
        </div>
    )
}


export async function getStaticProps() {
    const dirToList = '/opt/'
    const files = await fs.readdirSync(dirToList);
    const filesObject = new Array();
    for (let i=0; i < files.length; i++) {
        let file = {
            dirId: i+1,
            name: files[i]
        };
        filesObject.push(file)
    }


    return {
        props: {
            lists: filesObject
        }
    }
}

export default ListPageComponent;


In the above, we created an array of files using readdirSync() function.


const files = await fs.readdirSync(dirToList);


readdirSync() reads all the files in the directory and assigns it to the files array. And then we initialize an object Array and push the list of files in it.


As we already said, getStaticProps() will return the object, hence we return it to the page component. 


Visit http://localhost:3000/lists, you will see all the directories under the /opt folder.


Now, our pages are pre-rendered. But there is still an issue with this approach. What will happen if we create another directory in the '/opt' folder?

Our page is already generated, so we will not see the new directory on the '/lists' url (unless you are on the development server). 


In the development server, it will build the pages every time you save the configuration. But in the production server, users will unable to see anything on the URL. 


We need to tell Next.js to regenerate a page in regular interval so it wouldn't miss any new updates on the server.


revalidate: 10


Revalidate() reruns the getStaticProps() and regenerate the page after 10 seconds (It could be any value of your choice). It is Incremental generation of the page. Now our code looks like


import fs from 'fs'
function ListPageComponent(props) {
    return (
        <div>
            <h1>List of Folders</h1>
            <ul>
                {props.lists.map(list => <li key={list.dirId}>{list.name}</li>)}
            </ul>
        </div>
    )
}


export async function getStaticProps() {
    const dirToList = '/opt/'
    const files = await fs.readdirSync(dirToList);
    const filesObject = new Array();
    for (let i=0; i < files.length; i++) {
        let file = {
            dirId: i+1,
            name: files[i]
        };
        filesObject.push(file)
    }


    return {
        props: {
            lists: filesObject
        },
        revalidate: 10
    }
}

export default ListPageComponent;


Summary

In this article, we learn how to use the getStaticProps() to pre-render the Next.js page for faster loading of pages.