React Portfolio
Updated on June 26th, 2021 at 1:01 am
What is it?
This is a website that I created to act as a collection of smaller applications. The purpose of the site is to demonstrate my skill with JavaScript and React. The entire website is powered by React and Node. The routing engine is powered by React Router (BrowserRouter), the webserver is hosted with Node, and all of the logic is written in JavaScript ES6 and JSX.

What does it do?
I created three apps in the React Portfolio (one of which is still under construction).
Music Master

Music Master was a project that I completed from a section in a Udemy course that I took on React. The app uses React Fetch to extract data from the Spotify API. Spotify provides an external API that developers can use to send queries to their music search engine and find artists by name. With that information, I was able to retrieve basic information about the artist (like their followers on Spotify, and what genre they play under), as well as information about the albums and tracks under their name.
The search engine will find the closest result to your query and display the artist and their top tracks. Each track will show the album art, its title, and (if Spotify has a preview for that track) a 30-second demo of that song.
AniWow

AniWow was a project that I created after Music Master as a challenge to learn more about React. Unlike Music Master, however, AniWow uses Axios to handle the data fetching. This is partly because instead of using GET requests, AniWow’s data fetching utilized a technology called GraphQL which only works with POST requests. I decided to use the AniList API since it was free to use and had a very extensive anime database.
The AniWow app displays a whole bunch of information from a single GraphQL query. The information includes:
- Show Title (Japanese)
- Show Title (English)
- Show Description
- List of Streaming Services that support it
- List of links to show page on those Streaming Services
- Season Artwork
- Show Genre(s)
- Episode Count
- Character Names
- Character Profile Picture
- Actor Name that played each Character
- YouTube embedded Trailer (if available)
The GraphQL query that retrieves this information looks like this:
query($queryString: String!) { Page { media(search: $queryString) { title { romaji english } coverImage { large } characters(page:1) { edges { node { id image { large } name { first, last } } voiceActors(language: JAPANESE) { name { first, last } } } } genres description episodes trailer { id site } externalLinks { id site url } } } }
How does it work?
The website is made of 21 files plus 4-5 files for each project. The routing is controlled by App.js
which uses BrowserRouter to control how the URL structure works. index.js
contains the ReactDOM render function. The list of apps on the main screen are controlled by a JSON file that contains information about each app, including its id, title, icon, description, relative file location, and the default search queries (if applicable). Some of the apps may automatically search for something at random so that the screen is not blank when you enter the app. The header and footer are broken up as components with slots for dynamic content.
Each app consists of a single page and a single parent file makes up the content of the app. Some of the app’s functionality, however, are created as components (in separate files) that use props generated from the parent file. For example, in Music.js
, the “artist” and “tracks” section of the app are individual components that use the data retrieved from the state variables in Music.js
. These state variables are populated from the fetch function that runs a query on the Spotify API to retrieve information.
The Music.js
file has two state variables (artists and tracks) that are populated via the fetch function that sends a GET request to the Spotify API.
state = { artist: null, tracks: null } ... // If there is a result if (json.artists.total > 0) { let artist = json.artists.items[0] this.setState({ artist }) // Get the tracks from the associated artist fetch(`${API_ADDRESS}/artist/${artist.id}/top-tracks`) .then(response => response.json()) .then(json => this.setState({ tracks: json.tracks })) .catch(error => alert(error.message)) } ...
The artist and tracks’ components then pass the values of the state variables as props.
<section id={'content'}> <Artist artist={this.state.artist} /> <Tracks tracks={this.state.tracks} /> </section>
In the Artist.js
component, the prop (which is passed as an array) is broken up into a series of variables that are printed through elements on the page.
const Artist = ({ artist }) => { if (!artist) return null const {images, name, followers, genres, external_urls} = artist return ( <div id={'artist'} className={'container'}> <img src={images[0] && images[0].url} alt="artist-profile"/> <h1 className={'display-4'}>{name}</h1> <p className={'lead'}>{followers.total} followers</p> <p>{genres.join(',')}</p> <a href={external_urls.spotify} className={'btn'} target={'_blank'} rel="noopener noreferrer"> View on Spotify </a> </div> ) } export default Artist
All of the apps work through the concept of passing props (which are populated by state variables) through various components that represent different sections of data.
The code repository for the project is viewable by clicking the “Bitbucket Repository” at the top of the page. Additionally, you can see all of my planned and completed tasks for the project on my Trello board which is viewable by clicking the “Trello Board” at the top of the page.