How to Build a Profile Page in React with Spotify API Data
Build out and style the profile page
This lesson preview is part of the Build a Spotify Connected App course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Build a Spotify Connected App, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:13] All right, so just like with the login page, we're going to create a file called profile.js in our pages directory. So we can use that component and render it in our home page or index route.
[00:14 - 00:22] So if we go on over to pages and we create a profile.js file. And then in here, it's going to look something like this.
[00:23 - 00:42] And again, these codes and the bits are going to be available in the manuscript below, so feel free to grab it there. But as you can see, it basically does the same thing we were doing here with pulling in getCurrentUserProfile and having a useState hook with a useEffect hook here where we fetch the data.
[00:43 - 00:51] We await it and then we set it to our state variable. And then in here, we just render the JSX.
[00:52 - 01:10] So once we have that, we can go on over to our pages index.js file and make sure we export it here. And then in our app.js file, we can add it to our list of imports from our pages index file.
[01:11 - 01:23] And then down here, all we need to do is replace this fragment with our profile component. Give that a save and you can see it basically looks the same.
[01:24 - 01:40] But one thing we're missing is that logout button we just got rid of. So since we want the logout button to render on every single route, not just our home page, we can come up here and add that button back above our router.
[01:41 - 01:54] And we'll make sure it has an onClick handler that calls our logout function and will wrap it in a fragment. So React is happy.
[01:55 - 02:04] And while we're in here, we're going to give our logout button a few more styles. And we're going to create a style component for it called styled logout button.
[02:05 - 02:18] So I'll go ahead and replace this button tag with it. And then up here, I can just import our style components and add that styled logout button style component and make sure it's a button tag.
[02:19 - 02:31] Give it a save. We can see our absolute positioning in the top right corner is being applied and the rest kind of just looks the same.
[02:32 - 02:35] Awesome. So now let's pay attention to our profile.js file.
[02:36 - 02:52] So if we take a look at the Spotify web player, we're basically going to be trying to achieve what this looks like. So if we take a look at this header, there's five pieces of information that we are going to want to display.
[02:53 - 03:14] So that's the profile image, that's the current user's name, the number of play lists they have, the number of followers they have, and the number of people that are following them. And unfortunately, we're not going to be able to display the number of people following the current user because that data is not available on the Spotify API.
[03:15 - 03:26] If we take a look at our current profile page, we already have the name, the number of followers in a profile image. So let's give those some styles.
[03:27 - 03:38] So let's head over to our styles directory and we're going to create a style component called styled header. So I'll call that styled header.js.
[03:39 - 03:47] And then in here, it's going to look something like this. And again, feel free to copy and paste this snippet from the manuscript below.
[03:48 - 03:54] There's nothing too fancy going on here. There's Flexbox being applied to properly align and space things.
[03:55 - 04:10] There is a header image tag that we can take a look at. And basically, the special thing that this selector is doing is for the border radius property, it's looking at the type prop that's being passed to the styled header style component.
[04:11 - 04:26] And if that prop is equal to user, then we set the border radius to 50%, basically making sure that the profile image is a circle. But if the type prop is not user, then we just set it to zero.
[04:27 - 04:43] And the reason we're doing this here is because we're going to be reusing the styled header style component on different pages, like for artists and playlists, and on those pages, we don't want the image to be a circle. We're going to want them to be a square.
[04:44 - 05:05] So next, we can go to our styles in next.js file and export style header. And then we can go back to our profile.js file and import that styled header style component.
[05:06 - 05:24] And then down in our return statement, we can replace this div with our styled header style component. And as you can see, I updated the templates a little bit to conform to the class names that we are targeting in the styled header style component.
[05:25 - 05:37] Give that a save. And now our header should look something like this. Cool. So now the only piece of data that we're missing in our header is the number of playlists.
[05:38 - 05:50] So unfortunately, that data doesn't come back from the /me endpoint from the Spotify API. So we're going to have to add another function to hit another API endpoint to get that data.
[05:51 - 06:07] So under getCurrentUserProfile, we can add this getCurrentUserPlaylists function, which hits the /me/playlists/spotify API endpoint. And this endpoint gets a list of the current user's playlists.
[06:08 - 06:20] And in the JSON response, it basically just returns a array of playlists objects. And as you can see, one of the query parameters on this API endpoint is a limit query parameter.
[06:21 - 06:32] So our getCurrentUserPlaylist function has a default argument of 20 for this limit variable. And then we just pass that in a query parameter in our get request.
[06:33 - 06:46] Next, we can import this getCurrentUserPlaylists function to our profile.js file. And then in our profile function, we can add another useState hook.
[06:47 - 07:00] And we'll call this playlists and set playlists. And then down in our use effect hook, we can just add another await function here.
[07:01 - 07:20] And instead of getCurrentUserProfile here, I will call getCurrentUserPlaylists and then make sure we're setting the playlist state variable. And then here, since we can't have two data variables, I'll just call this user profile in camel case.
[07:21 - 07:36] And then instead of just data, I'll set profile to user profile.data. And same here, I'll get rid of the destructuring and say setPlaylist to user playlist.data.
[07:37 - 08:01] And to make sure we're getting the JSON data we need back, we can console log this userplaylist.data. And then in our localhost 3000, if we pop open the console, we should see, other than all of these warnings, that there is an object being logged and it looks like we have all of our playlist objects.
[08:02 - 08:29] Now in our profile.js file, we can get rid of that console log and then down where we have our metadata down here, our paragraph tag, we can update this to include playlists, number of playlists , and then number of followers. Give that a save. And now we should see that I have 44 playlists and 25 followers.
[08:30 - 08:49] Okay, so next up, now that we have our header displaying properly, we're going to move on to the top artist section. So we're basically going to do the same song and dance here. We're going to head on over to our spotify.js file because we need data from a different Spotify API endpoint.
[08:50 - 09:04] And then here, under get current user playlist, we're going to add another function called get top artists. And basically, what this function does is it calls the slash me slash top slash artist endpoint.
[09:05 - 09:19] And as you can see, this endpoint gets a user's top artists and tracks. And we're specifying that we want the user's top artist because we pass it a type path parameter. So our type is artists.
[09:20 - 09:32] The other thing we can note here is that this endpoint has a time range query parameter. And the value of this query parameter determines the timeframes in which the data is computed.
[09:33 - 09:49] So if you take a look at the documentation, the valued values are long term, which is basically all of the data you have. There is medium term, which is the last six months, and short term is the last four weeks or the last month.
[09:50 - 10:11] Now, just like we did for our current user's playlist, we can import this get top artist function to our profile.js file. And then we'll add another use state hook for it. We'll call this top artists.
[10:12 - 10:32] And then in our fetch data function, we can do the same thing. We'll call this user top artist. And then we'll await our get top artists function. And then here, we'll say set top artists.
[10:33 - 10:49] And just like we did last time, let's take a look at the JSON data coming back. And if you give that a save and head on over to your local host 3000, you should see that there is an error.
[10:50 - 11:16] And this error is a 403 error. So what's going on? So a 403 response code means that the server understood our request, but it refused to authorize it. So why is that happening? If we take a look at the documentation a bit more, it says that getting details of a user's top artist in top tracks requires authorization of the user - top - red scope.
[11:17 - 11:41] And if you think back to what we were doing in our express app, we have a scope variable here, which we are passing to the Spotify account service when we are getting our authorization token. So all we need to do here is add user top red to our list of scopes.
[11:42 - 12:02] And while we're in here, we can refactor our code a bit to use an array to easily keep track of these different scopes. And with this array, we can just add a dot join here and join them with spaces.
[12:03 - 12:27] Now, if we head back over to our app, and we first log out and log back in because we need our access token to reflect those updated scopes. Now we can see that our console log is coming back with JSON and all of these items are objects of artist data.
[12:28 - 12:47] Cool, so now that we have data for our top artists, we can go ahead and build out the UI to display those top artist items that we got back from the API endpoint. So since we're planning on creating a page for just top artists, we can plan ahead and create some reusable React components to handle this.
[12:48 - 13:02] So we're going to create a new components directory under our search folder. And here I'll first add a artist grid.js file.
[13:03 - 13:18] I'll also add a section wrapper.js. And just like all of the other folders we have, I will add a indexed file.
[13:19 - 13:27] So our artist grid component is going to look something like this. And basically, this component takes an artist prop.
[13:28 - 13:43] And if that artist's array has a length, then we go through and we map over each artist and we create a list item for it. And with each list item, we render the artist image, the artist's name, and a little artist label.
[13:44 - 14:02] And if there are no artists, then we just render an empty no artist available message. This component also pulls in a styles grid style component, which we're going to be adding in just a second.
[14:03 - 14:14] Next we have section wrapper, which is going to look something like this. And this component is basically what we're going to wrap our artist's grid component in on the profile page.
[14:15 - 14:41] We're going to use this component every time we have a new section, just to make sure it's consistent in HTML structure and style, like padding, heading styles, etc. Then in our components index.js file, I will just export those two components.
[14:42 - 15:02] The next thing we're going to do is go to our styles directory and add these styles section and styled grid style components. So in here, I will create a styled section.js and that is going to look something like this.
[15:03 - 15:19] Basically, it's just a section tag and it targets a bunch of different classes within the section to consistently style them. And then we'll also add a style grid component.
[15:20 - 15:36] And this style component is going to be an unordered list and it's going to use CSS grid to create this grid effect. And then we'll also make sure to export those in our index.js file.
[15:37 - 15:56] Okay, so now that we have all of these new style components and abstracted react components, we can come on over to our profile.js file. And then let's first import the section wrapper and artist's grid component from our components directory.
[15:57 - 16:14] So here we'll say import section wrapper and artist's grid from components. And then down in our return statement under our profile ternary here, we can add another ternary.
[16:15 - 16:34] And if we have our top artists data, then we can render this main tag. If we give it a save, you can see that here we now have our top artists this month showing up here in our styled grid.
[16:35 - 16:48] And note that we are passing our artist's grid just 10 items because we just want to keep our profile page tidy. We don't really need to show like 20 artists.
[16:49 - 16:56] Okay, so next we're going to build out the top track section. Our goal is for it to look something like this.
[16:57 - 17:27] So in here we're just going to have a bunch of list items and we're just going to render the name of each track, we'll notice the album and the duration of the track. So just like our profile data and our top artist data, we're going to go through the same song and dance of adding a function to the Spotify.js file, adding that fetch to our profile.js and then rendering some JSX with it.
[17:28 - 17:44] So below get top artists, we're going to add a get top tracks function. And it basically is the same as get top artists, but in here we pass the type path peram as tracks instead of artists.
[17:45 - 18:04] Then in our profile.js file, we'll import that get top tracks function. And then we'll add another state variable for it called top tracks.
[18:05 - 18:23] And then just like last time, we'll add it to our fetch data. And we'll console log that data to make sure the JSX coming back.
[18:24 - 18:40] So it looks like we forgot to replace the set top artists with set top tracks. Cool, so now that we have that data to work with, next thing we're going to do is create a new component to display our tracks.
[18:41 - 18:52] So under our components directory, we'll add a new track list.js file. So here we'll add our template.
[18:53 - 19:10] And then we will export it from our index.js file. If we take a closer look at our track list component, you'll notice that there are two imports up here of things that we don't have yet.
[19:11 - 19:32] So that is the format duration util and the styled track list style component. So format duration is just a function that formats a number of milliseconds, which is what comes back with the JSON data as the duration for each track into a human readable time.
[19:33 - 19:45] So that function is going to live in our utils file, which we have over here. And underneath catch errors, we can add our format duration function.
[19:46 - 20:01] Next, we're going to add this styled track list style components in our styles directory. And it'll look something like this.
[20:02 - 20:21] It's also an unordered list, and it uses CSS Grid to basically create all of those list items for each track. And then we will export that from our styles index.js file.
[20:22 - 20:37] And then we can head on over back to our profile.js file and import that track list component. And then we will get rid of the console log here.
[20:38 - 20:47] And then we'll use top tracks to add another section to our profile page. So we'll update this here.
[20:48 - 21:00] We'll say if they're top artists and top tracks, we will render this main tag. And we have top tracks this month for our section wrapper.
[21:01 - 21:15] If you get that a save and scroll down in your local host 3000, you'll see that we have this top tracks section here. And we have the first 10 top tracks you have this month.
[21:16 - 21:24] Alright, good work. So now the last thing we're going to add to our profile page is the playlist screen.
[21:25 - 21:43] So since we already fetched our playlist data from the Spotify API for the header, we can skip right to adding and styling the template. Just like we did for artist screen, we'll create a playlist screen.js file under our components directory.
[21:44 - 21:50] And that's going to look something like this. It's very similar to artist screen in that it has a playlist prop.
[21:51 - 22:00] And if that playlist is an empty, we render our style green component. And notice that we don't pass it a type prop like we did for artists.
[22:01 - 22:16] So our playlists, the images won't be circles, they will be squares. Another thing to note here is that we're using the react router link component to wrap a link around every playlist item.
[22:17 - 22:35] Because we're going to be creating a individual playlist page for each playlist and we're going to be doing that in a future lesson. Next, we can go to our components index.js file and export that playlist grid component.
[22:36 - 22:49] And then in our profile.js file, we will import it. And then down below, we can update our template to add that section.
[22:50 - 23:06] So we'll just add playlists to our ternary and render this third section wrapper. Give that a save and you should see 10 playlists being rendered here since we grabbed the first 10.
[23:07 - 23:19] And each playlist should be a link to a playlist page with the ID attached to the end. Awesome. So we are all done with our profile page.
[23:20 - 23:28] And that was a lot of code and a lot of work. But if you haven't noticed already, there is this pattern that we've been repeating a few times.
[23:29 - 23:40] And that pattern is so for each component, we added a function to our spotify. js file to hit the right spotify API endpoint to get our JSON data.
[23:41 - 23:53] And then we created a new file for that component if we needed it, like an artist grid or a playlist grid. And then after that, we added the style components for it.
[23:54 - 24:04] And then we imported all of those components to our profile.js file. Like our section wrapper, our artist grid, tracklist, etc.
[24:05 - 24:23] And then we made sure to fetch all of the data we needed from the functions in our spotify.js file. And then down below, all we did is use our section wrapper, style components to render each section and render the data.
[24:24 - 24:32] Alright, so in the next lesson, we're going to be building out the top tracks and top artist pages.