The Case for Static Data Fetching
All right then gang. So now, hopefully you've got a feel for the basics of creating a Next application: how to make pages and routes, how to link between them, how to use styles, how to create a layout component, and now also how to use static assets. The next step for us is to make the website a bit more dynamic and to bring data into the mix. For example, it would be nice to fetch some data from an API endpoint which we can then show in one of our page components.
In our case, that's going to be some ninja data. Now, normally this data would come from a ready-made API endpoint that we might create or directly from a database like Firebase. I want to keep it simple and I'm going to be using JSON Placeholder. Now, JSON Placeholder gives us some dummy API endpoints to fetch data from, really good for testing. And we can choose different resources, so there's posts, comments, albums, photos, to-do's, and users. And this is how many items we get back from each endpoint. We're going to use this one right here: /users. So watch, if I click on this right here, this is the endpoint, and we can see this is the JSON data we get back. So loads of different objects where each one is a user; it represents a user. In our case, it's going to represent a ninja.
Now ideally, we don't want to just request this in the browser in the address bar; we want to request this data from our code instead. So how do we do that? Well, in normal React applications, we might do this from a hook like useEffect, and that would make the request in the browser. But in our case, we don't want to do that, because remember, the components are all pre-rendered by the time they reach the browser. So ideally, we want to fetch the data before they're rendered so the rendered components have data in the template.
Introducing and Implementing getStaticProps
And to do this, we can use a special function provided to us by Next. So I'm going to show you that now.
First of all, where are we going to fetch the data? Well, we're going to do it inside this ninjas index component right here. So when we go to /ninjas, this is where we're going to fetch the data from and show the data.
So the special function that we need to create provided to us by Next goes up here, and this function is called getStaticProps, and we need to export this. So I'm going to say export const getStaticProps like so, and that is equal to a function. And inside the function is where we fetch the data. And this is an async function, let's spell const correctly, like so. So this function right here runs at build time as our app is built and our components rendered. At this point, we can add a fetch request inside it to fetch any data we need for our component template. Now, this function never runs in the browser, only at build time, so don't write any code here that you expect to run in the browser.
Let's now create a fetch request inside this function. So I'm going to say const response = await and we can use await because this is an asynchronous function, and then we're going to use a fetch request. The endpoint is going to be this thing right here to fetch the users, so let's copy that and place it inside here. So that's the fetch request. That returns a response object. Now to get the data from that, we have to use the JSON method to pass that JSON into something we can work with. So we'll say const data = await, because this is also asynchronous, this json method. And now this is going to be an array of objects like this thing right here.
Passing Fetched Data to the Component
Okay, so we have that data, but then how do we actually use it inside the component? Well, we return a value from this function, and this return is going to be an object, and inside that we have a props property, and we give this a value. Now, this value is going to be an object, and inside here we can pass in different properties and values that we want to make accessible inside our component as a prop. So in our case, I'm going to create one called ninjas. You can call it what you want, I'm calling it ninjas, and I'm setting that equal to data, which is this array of users.
So now what happens is this data is now available to us inside this component, and it's attached to the props that we take in right here. So I could just destructure from that the ninjas property. And that is all of this data. So remember, this runs before the component is rendered, fetches the data, it waits for that data; once we have it, it pumps it into the component so that it can be rendered with that data inside it.
Rendering and Debugging the Data List
Okay, so now what we need to do is map through those ninjas and output them in the template, which is what I'm going to do. So curly braces, because we're using dynamic JavaScript right here. So ninjas.map to map through them. And then we're taking each individual ninja as we cycle through those and fire a function for each one whereby we return some kind of template. So let's get rid of the curly braces right here and instead return parentheses, because we're just returning template inside these parentheses. And the first thing we'll do is a div, and the root element inside this needs to have a key. This is all standard React stuff, so if you don't understand any of this, then definitely check out my React series first of all.
Now each ninja right here has an id property on it. We can see this thing right here, so that is going to be the key. So ninja.id. And then inside that, all I'm going to do is output an anchor tag without an href. We'll add in the link later, but this anchor tag is going to have a class name so we can style it later on. And in fact, we'll leave that off because we've not made the styles for it, and we'll do that shortly. But what I'm going to do is output an h3 inside this that outputs the ninja.name property. And again, that name property is on the data right here. So we're just listing the ninja names here, that's all we're doing.
So hopefully now if I save this... okay we get an error, and this says "cannot read property map of undefined". So let's see what's going on over here. Okay that all looks okay, so I'm just going to refresh over here to make sure that we just needed to refresh. That's fine now. Okay, we just needed to refresh. All right then. So that looks like it's all working. Cool. So that's how we fetch data. We use this function right here, getStaticProps, it's an asynchronous function, we can fetch data inside it, we return an object with a props property, and that is an object where we can attach different properties for data we want to pump in to our component. Pretty simple.
Styling the List and Next Steps
Okay, so let me finally just add in a few styles to this ninjas.css module. So I'm just going to paste these in like so. And what I'm going to do is apply this class single to this thing right here, this anchor tag. So let's say className is equal to something, and first of all, we need to import those styles. So let's do that. I'm going to say import styles from, and then we need to come up two layers and then into the styles folder and then we want the ninjas.module.css file. Okay, so now down here we can apply styles.single like so. And all that class does is give each one a bit of padding, a background of white, display, some margin, and a border left. And then when you hover over it, that border left turns blue. So if I save this and preview, that looks a lot nicer.
Okay, so next up, we're going to look at dynamic routes to make ninja details pages when we click on these things right here.