Building the Furry Friends Gallery Mark II
We've seen the finished app, so now it's time to build it! This lesson will take you, step by step, through creating a brand new app, the Furry Friends Gallery Mark II.
Building Furry Friends Gallery Mark II#
So here we are, ready to expand our API fetching and handling knowledge using the Axios package and grabbing data from TheDogAPI - Dogs as a Service.
We’re going to move to this slightly different API provider for a few reasons:
It handles paging via the API.
It deals with API keys and sending them via request headers.
It offers more flexibility in the data that we can receive.
Overall, however, The Dog API will allow us to simulate a more realistic environment for requesting and receiving data in a realistic project; after all, this is The Beginner’s Guide to Real World React!
Our first move will be to set up a new project using the Create React App helper, so let’s get started.
Open up a terminal window and navigate to the parent folder that you want to create the new project in. Next, type the
create react-app command as follows:
Let the command line finish installing the dependencies, wait until you see the ‘success’ message and
yarn commands to start and build the app.
Testing the new project#
As we did in the last project, it’s always best to spin up the default, unchanged app that we just made to make sure we’re starting from a solid, — and more importantly — working base.
So, follow the advice in your terminal output and enter the following commands:
Once the project’s built and launched, you should be able to fire up
http://localhost:3000 in a browser and see dark background and spinning React logo that you’ll soon come to know and love.
Cleaning up the starter project#
Create React App does load in a few bare-bones files and styles to give you a jumping-off point. However, we’ll need to make a few changes to get everything cleaned up and ready for our new gallery app.
index.js, located in
/furry-friend-gallery/src/ and remove the following line:
It should be on line 3 of the
index.js file. This will just remove a link to the default styles from the project that we won’t need.
After that, locate
/src/index.css and delete the file.
Next, find the
/src/App.css file and open it up. Highlight all the contents and delete the existing styles. Save and close the file.
Finally, open the main
App.js file located at
/src/App.js. This currently contains a lot of starter JSX which we’re going to replace, as well as a link to a logo file that we’ll want to remove.
First, locate the following line (around line 2) that imports a
logo.svg file, and remove it:
import logo from ‘./logo.svg'
Now, select everything in the return statement (everything between
return ( and
)) and replace it with the following so that the new return statement looks like this:
Our project still contains a few default files, components, and assets that are loaded in by default, but we’re not going to worry about them for now as they’re not doing any harm just sitting there, and they’re not currently being loaded anyway.
Adding project dependencies#
We’ll create and edit the files we need to get our project running, but first, we need to add a couple of dependencies to our project.
Bringing Axios onboard#
The first dependency to add is the Axios npm package. We’ve talked about the benefits of Axios already, but if we want to access those benefits and everything Axios offers, it’ll need to be part of our app.
Fortunately, it’s very straightforward to add. Back in a terminal window, make sure you’re in the root project location and enter the following command:
That’s it, quick and simple. Now, we can import Axios and any of its helper methods using the import statement,
import axios from ‘axios'.
We could add Bulma as a dependency just like Axios, but for familiarity’s sake, we’ll add it in the same way we did in the last project.
Open up the file
/public/index.html . If you remember, this is the template HTML file that the project uses to render the initial output of the app.
Next, add the following line somewhere between the opening and closing
You can also edit the title of the page between the
<title></title> tags too if you like.
Creating our app’s files#
Now that we’re going to be implementing a data handler of sorts to act as a middle man between the API and our components, there are a couple more files that we’re going to be using:
App.js— the familiar project starting point where all the magic happens.
DogCardInfo.jsx— a slightly modified component from the previous project that displays a dog picture and id value.
BreedList.jsx— a self-contained data-fetching component that will handle its own data needs and display a list of breeds to filter our main picture list on.
App.css— we’ll add a few additional styles in here to make the dog card components look a little nicer.
.env— a new type of file that holds key variables that might change between environments. We’ll store our API key and other data in here.
api.js— this will be our data handler-like library that will be responsible for interacting with the API and returning it to the calling component.
So let’s start editing our files and putting all the pieces together.
Obtaining an API key#
There are a lot of free APIs out in the world, but most that you’ll come across usually offer their wares from behind an authentication key. This helps to limit abuse and helps the API provider to keep track of the volume of requests across a given range of accounts.
In that respect TheDogAPI - Dogs as a Service is no different. Fortunately, it’s really simple to request an API key from them.
First, head over to https://thedogapi.com and click on the large blue button saying ‘SIGNUP FOR FREE’.
You’ll be taken to the following page where you can enter your email address and a brief description of what you’ll be doing with your app.
After hitting ‘SIGNUP’, you’ll see a thank you screen and a message to check your inbox for the key. Head on over to your email and you should receive an email containing your shiny new API key like this:
With our API in hand, it’s time to take a quick look at the documentation, which is another important aspect of your role as a frontend developer, especially when working with APIs.
Experimenting with The Dog API documentation#
Out in a real-life frontend role, you’ll very likely come across a situation where you have to connect to APIs somewhere out in the wild to fetch important data for your UI. When facing this, you’ll hopefully have access to quality API documentation that outlines what endpoints are available, as well as information that explains how to call the endpoint — what parameters to supply, what the format of the data returned is, and so on.
With that in mind, let’s take a quick look at The Dog API documentation. Fire up the URL in your browser of choice and you’ll see a screen similar to this.
The top links in the left-hand sidebar all refer to features and functionality of the API along with details on how to authenticate to the API in order to use it.
Under the ‘API Reference’ heading, however, is where we’ll find information about the specific endpoints that the API exposes. Click on ‘breeds’ and then ‘List the Breeds’ to view that page.
You can see that the page contains information about authorization, which parameters you can supply to the
/breeds endpoint (in this case there are three), as well as the response data that you’ll receive following a successful call.
The most useful part of this page for me is the ‘Send a Test Request’ section. If you hit the orange ‘Send’ button, the API will generate a sample call with real data.
Note the API URL,
https://api.thedogapi.com/v1, we’ll be making use of this in a moment.
The response from the test API call looks like this:
This is key for us as it helps us shape the JSX in our components now we know what data is available and the shape of that data.
Creating .env file#
A file without a name but with some variation of
.env as the extension is an environment file. It contains environment variables, which are pieces of information specific to particular development environments.
For example, you might have a staging file and a production one, each containing the same variable names but with different values, each specific to their respective environments.
There are no hard and fast rules to what you can keep in such a file, but generally, you’ll store relatively insensitive information that changes between different environments, such as URLs, names of things, or version numbers.
For us and our project, however, we’ll store the API URL and our API key in a
.env file of our very own.
At the root of our project, create a new file and don’t give it a name. Instead, just type the file extension directly, so it should read
With that done, open the file and add the following information:
Notice the API that we noted before,
https://api.thedogapi.com/v1/ . This is the base URL to call the dog API; we’ll be appending with specific routes like
/breeds later on.
The important point to remember here is to replace
[YOUR API KEY] with the API key that The Dog API sent to you via email!
.envfiles, you can put whatever variable and value combination you like in there. However, when it comes to Create React App, if you want to use any of the variables in here, you’ll need to prefix them with
REACT_APP_or they won’t be read. For example, if you want to use a variable called
DINOSAURyou must name is
REACT_APP_DINOSAURin here. Create React App does this to avoid exposing anything that it shouldn’t that shares the same name. You can read more about environment variables and Create React App in the official docs.
DogCardInfo.jsx component is very similar to the last one we created as part of the previous project. We do have a couple of small tweaks because of what data is available to us from The Dog API though so let’s get going.
If you don’t have a
/components folder underneath your
/src folder then create that now. Next, create a new component file within this new folder and call it
Copy in the following component body:
There’s nothing particularly special or fancy about this component, it’s merely a repeatable presentational component that will be used to show a nicely styled picture of each dog picture that’s returned from the API.
The main difference here is that we’ve brought in a
pictureId value that’s unique to each picture. We’re going to use it to display it under the picture of each dog, purely for presentational reasons.
With the existing
App.css file that comes with the Create React App project starter, we need to update the styles so that our dog pictures and radio buttons for breeds look much nicer.
Open up the
/src/App.css file and replace the default starter contents with the following:
As well as making each dog picture card component have a sensible height, we’re making sure each breed radio button is displayed on its own line and playing with the spacing a little.
Now for the really interesting part…fetching our data! Start by creating a new folder called
lib under the
/src folder. Next, create a new file,
Create a new folder within the
/src folder called
/lib, and then create the
api.js file. Now let’s start filling out the API methods.
api.js file, we’ll be introducing the concept of a data handler. Put simply, a data handler is a middle man of sorts that handles the communication between a data source and a data consumer. In our case, the data source is The Dog API and our data consumer is any component that wants information from the API, such as the
You could, of course, just have the code directly in each component, which is fine for small projects. But as soon as you start to repeat this API handling code things start to get messy:
If you need to change something in the API fetching code, you’ll need to change it in multiple places.
Your components grow larger with additional API handling methods.
Your components start to widen their responsibilities.
Handling errors becomes more complex and distributed.
However, by abstracting this data fetching and handling facility into a single place, a data handler, we centralize all of this logic and responsibility into one place. In reality, you might have a few data handlers that deal with different areas of the API, but the point of a data handler remains the same.
We gain a lot of benefits:
Only one place to edit and maintain data handling code.
Our component code becomes more DRY (Don’t Repeat Yourself) and adheres to the Single Responsibility Principle (SRP) more closely as it should now just be dealing with just handling incoming data and presenting it.
Errors are localized in one place.
We only need to define one interfac