Fetching Data from a Third-party API with Vue.js and Axios – SitePoint

More often than not, when building your JavaScript application, you’ll want to fetch data from a remote source or consume an API. There’s lots of cool stuff that can be done with data from a range of publicly available APIs.
With Vue.js, you can literally build an app around one of these services and start serving content to users in minutes.
I’ll demonstrate how to build a simple news app that will show the top news articles of the day, and that will allow users to filter by their category of interest, fetching data from the New York Times API. You can find the complete code for this tutorial here, and a live demo of the finished app here.
Here’s what the final app will look like:

To follow along with this tutorial, you’ll need Node.js and (optionally) Yarn installed on your machine. To install Node, you can either head to the official download page and grab the Node binaries for your system, or use a version manager instead.
Once Node is installed, to pull in Yarn, run:
npm i -g yarn

You’ll also require a basic knowledge of Vue.js. You can find a great getting started guide for that here.
Acquire an API Key
To make use of the NYTimes API, you’ll need to get an API key. So if you don’t already have one, head over to their signup page and register to get an API key for the Top Stories API.

We’ll be using the top stories API endpoint to fetch data from. Take note that there are multiple sections such as “home”, “travel”, “arts” and “science” that this API provides. We’ll need to build a filter that can allow users to select a section and load the stories within it.
Below are example calls:

Feel free to use your favorite REST client (such as Hoppscotch or Insomnia) to test your API calls.

Project Structure
Let’s quickly spin up a Vue 3 project using Vite, a dev server that runs faster than Vue CLI:
yarn create @vitejs/app vue-news-app –template vue

cd vue-news-app
yarn install

yarn dev

Open localhost:3000 in your browser. You should have the following view:

Next, let’s install the TailwindCSS framework to provide some basic styling. You’ll need to stop the server in order to perform this action:
yarn add -D [email protected] [email protected] [email protected]

npx tailwindcss init -p

We’ll need some additional package utilities to help us format dates and clamp the number of lines for the abstract field:
yarn add @tailwindcss/line-clamp date-fns

@tailwindcss/line-clamp is a plugin that needs to be included in tailwind.config.js. Below is the full configuration:
module.exports = {
purge: [“./index.html”, “./src/**/*.{vue,js,ts,jsx,tsx}”],
darkMode: false,
theme: {
extend: {},
variants: {
extend: {},
plugins: [require(“@tailwindcss/line-clamp”)],

Next, create an index.css file in the src folder and add this code:
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
@apply antialiased text-green-900 bg-green-50;
font-family: “Gill Sans”, “Gill Sans MT”, Calibri, “Trebuchet MS”, sans-serif;

#app {
@apply flex flex-col min-h-screen overflow-x-hidden;

In addition to importing the required Tailwind CSS classes, we’ve included a few CSS settings to help us define the default theme of our application. We’ve also implemented a flex layout system to help us create a sticky header and footer for our application.
We’ll need to import index.css in src/main.js:
import { createApp } from “vue”
import App from “./App.vue”
import “./index.css”


Let’s now go ahead and define our application layout. First, clear out any existing components in src/components. Next, within the same folder, create these three files:
Copy the following code for each file:



Finally, update src/App.vue:

Execute yarn dev. The browser should refresh automatically.

With the application layout completed, we can now start building the core logic of our news app.
Building News App Components
Our application structure will be made up of three News components and one container, src/App.vue. The container will be responsible for fetching post data and populating the components.
First, we need to design the layout and look for these components. Hence we need some mock data to begin with. Create the file src/posts.json and populate it with the following data:
“posts”: [
“title”: “Stay Healthy When Exercising Outdoors”,
“abstract”: “Cold weather workouts do bring unique risks, but a little planning and preparation can help whether you’re going for a winter walk, trekking in snowshoes or sledding with the kids.”,
“url”: “https://www.nytimes.com/2021/02/06/at-home/exercise-outdoors-cold-weather.html”,
“byline”: “By Kelly DiNardo”,
“published_date”: “2021-02-06T23:40:05-05:00”,
“thumbnail”: “https://static01.nyt.com/images/2021/02/07/multimedia/07ah-OUTDOOREXERCISE/07ah-OUTDOOREXERCISE-mediumThreeByTwo210.jpg”,
“caption”: “”
“title”: “4 Skiers Killed in Avalanche in Utah, Officials Say”,
“abstract”: “It was the third such deadly episode in days and the deadliest avalanche in the United States since May 2014, according to the authorities.”,
“url”: “https://www.nytimes.com/2021/02/06/us/avalanche-salt-lake-city.html”,
“byline”: “By Michael Levenson”,
“published_date”: “2021-02-06T20:22:39-05:00”,
“thumbnail”: “https://static01.nyt.com/images/2021/02/06/lens/06xp-avalanche-photo2/06xp-avalanche-photo2-mediumThreeByTwo210.jpg”,
“caption”: “A helicopter returning to Millcreek Canyon after rescuing one of the four avalanche survivors on Saturday.”

I’d encourage you to duplicate the records in order to better test our component design layouts, but I won’t do that here due to space constraints.
Let’s now start building our News components. In the src/components folder, create the following files:
Just to visualize how all these components come together, import them in src/App.vue and set them out as follows:

Let’s break down the code above:
The header tag is where we display the current state value of section.
The NewsFilter component will contain a dropdown input for users to select a different section. There will be a button they’ll have to click in order to perform the fetch. We’ve bound the component to the state section to allow state synchronization.
The NewsList component will display posts using the NewsCard component across a responsive grid.
Let’s now start working with each individual News component. The NewsCard.vue component will present data for a single post. It requires one prop, post:

The NewsList.vue will loop through a posts array and populate NewsCards across a responsive grid:

Next, we have the NewsFilter component, which will allow users to load posts from different sections. First, we need a content file to store all the sections supported by the Top Stories API endpoint. Create the file src/components/sections.js:
const sections = [

export default sections

Let’s now create our NewsFilter.vue, which contains a dropdown select input and a button. We’ll need to use v-model to bind the state section in a way that syncs up with the state in App.vue:

The article “Vue 3: Data down, Events up” best explains the strategy we are using to bind section state to the NewsFilter component. Basically, this allows child components to update props and sync with the parent component.
Below is a screenshot of the current state of the application:

Using Axios to Fetch Remote Data
Axios is a promise-based HTTP client for making Ajax requests, and will work great for our purposes. It provides a simple and rich API. It’s quite similar to the fetch API, but without the need to add a polyfill for older browsers, and some other subtleties.
To install axios, run:
yarn add axios

The UI development of our application is complete. We now only need to implement remote fetching logic. Below is an example of the full URL format that NYTimes API service expects:

First, let’s store our API key in a .env file at the root of our project. Save in the following format:

Replace the hashes with your actual API key.
Since we’re using Vite, we need to comply with Vite’s manual on loading environment variables. Vue/CLI has its own instructions for doing the same.
Let’s now implement the logic that will fetch actual posts from the NYTimes REST API endpoint. Simply update src/App.vue accordingly:

Here we’ve created a function called fetchNews that contains logic for performing the fetch logic. This function will be called from two places:
The mounted() lifecycle event
The NewsFilter component
Let’s break the function down to make sure we understand what is going on:
We’re using async syntax, since it’s cleaner than using regular Promise callback syntax.
Since we’re about to perform a network call, many things can go wrong. We’ve wrapped the function’s code within a try…catch block. Otherwise, users will be met with a non-descriptive Promise error if one occurs.
Using ES6 template literals, we’re able to build a URL string that automatically gets updated whenever the user changes the news section via the NewsFilter component. Note that the API key has been included in the URL string as well.
After fetching results using the axios.get() function, we need to parse the results and format them in a way that’s compatible with our UI, specifically the NewsCard component. We do this using JavaScript’s Array.map function to create a new array with our formatted data.
Extracting image data is a little tricky. Some posts lack the multimedia field, and even if they do have it, there’s no guarantee that the media format we need is present. In such a case, we return a default image URL — http://placehold.it/210×140?text=N/A — and use the post’s title as the caption.
In the error block, we’re checking the presence of specific error properties to determine what kind of error has occurred. You can use this information to construct a helpful error message.
Now, take a look at the template section and observe that we’ve included a new prop called fetch, which links to the fetchNews function. We need to update src/components/NewsFilter.vue to accept this prop. Below, I’ve highlighted only the code sections you should change:

You’ll probably need to restart the dev server in order to properly load the axios library and the API key. Once you’ve done that, you should have a view of actual posts. Below is the current state of the application.

You should be able to switch and load different news sections.
Final Touches and Demos
I decided to add some minor (optional) touches to make the app experience a little bit better, like introducing a loading image.
You can see a demo in the StackBlitz below (limited functionality):

Alternatively, you can view a live version here.
In this tutorial, we’ve learned how to start a Vue.js project from scratch, how to fetch data from an API using axios, and how to handle responses and manipulate data using components and computed properties.
Now we have a functional Vue.js 3.0 app, built around an API service. There are loads of improvements that could be made by plugging in some other APIs. For example, we could:
Automatically queue social media posts from a category using the Buffer API
Mark posts to be read later, using the Pocket API
… and so on.
The entire code for this project is also hosted on GitHub, so you can clone, run, and make any improvements you fancy.

Coded at

Share your love

Leave a Reply