Finally, interesting stuff, after we finish with UI we can move to implementing the main functionality. So in this article, we will talk about fetching data from the server and storing it in the Pinia storage, also we will dynamically render our shop list and product page. As usual, we will start by defining the plan of work that needs to be done:
- Configuring Simple Axios Module
- Fetching and Rendering Products List
- Setting Product Dynamic Pages with Nuxt.js
Now that we have a clear plan in place, it's time to roll up our sleeves and get to work. We'll start by configuring the Axios module, which will serve as the backbone for fetching data from the server.
1. Configuring Simple Axios Module
We already installed axios in one of our previous posts: "Building Your E-Commerce Store with Nuxt.js: A Step-by-Step Guide to Project Setup", so now we can configure it and prepare for use.
Let's create the "http" folder inside our root directory, and inside the http folder create the http-client.js file. It will be a file for our main Axios settings and interceptors if we need them, but for now, we will only register Axios with the base URL.
import axios from "axios";
export const HTTP = axios.create({
baseURL: "http://localhost:3005",
});
Inside the "http" folder we will create a "services" folder that will store our axios services for separate app functionality. Inside the "services" directory create the first service products.service.js it will store our REST API services for products.
We can add the first two get functions with axios, for that we simply need to import HTTP and create an arrow function that will return data from the request.
import { HTTP } from '../http-client';
export const getAllProducts = () =>
HTTP.get('/products').then(({data}) => data )
export const getProductById = (id) =>
HTTP.get(`/products/${id}`).then(({data}) => data )
As you remember we also installed "json-server" to imitate the backend server, and prepopulated it with a products array, we can update product data and create more products like this:
{
"id": "1",
"name": "Product 1",
"instagram": "https://instagram.com",
"pinterest": "https://pinterest.com",
"image": "https://images.pexels.com/photos/2081332/pexels-photo-2081332.jpeg?auto=compress&cs=tinysrgb&w=600",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"price": 100
},
Now, we have a ready-to-use dev server with product data and functions that will call that server API. Our next step will be implementing this data fetching into product pages.
2. Fetching and Rendering Products List
Create a new products.js store, and add a "productsList" variable that will store a list of products received from the server, and a "product" variable that will store separate products for Product pages. Then we will add two actions that will use Axios services to fetch data from the server and set it to the state. And do not forget to add getters.
import { defineStore } from 'pinia';
import {
getAllProducts,
getProductById
} from '@/http/services/products.services';
export const useProductsStore = defineStore({
id: 'products',
state: () => ({
productsList: [],
product: null
}),
actions: {
async aGetAllProducts() {
await getAllProducts()
.then((data) => {
this.productsList = data;
})
.catch((error) => {
console.log(error);
})
},
async aGetProductById(id) {
await getProductById(id)
.then((data) => {
this.product = JSON.parse(JSON.stringify(data));
})
.catch((error) => {
console.log(error);
})
}
},
getters: {
gProductsList: (state) => state.productsList,
gProduct: (state) => state.product
}
})
Looks great. We can start using this store inside components.
Open our shop page, import products store, and inside the created lifecycle hook (it will fetch data before rendering the whole page) call our "aGetAllProducts" action.
created() {
const productsStore = useProductsStore();
productsStore.aGetAllProducts();
}
After that, we can use getters to get and render the product list. We need to send product list data to our product cards list.
<div class="products__content">
<ProductCard v-for="product in productsStore.gProductsList" :key="product.name" :product="product" />
</div>
Now we need to start json-server with the command: "json-server --watch db/db.json --port 3005". And start our Nuxt dev server in the separate PowerShell with the command: "npm run dev".
Now, after visiting or refreshing our Shop page we will send a request to our json-server for product data, and render that data into our page.
Awesome. But the problem is when we clicking on the product card we will be redirected to the product page with static data. Each page will show the same information and images, to solve this let's move to the next step.
3. Setting Product Dynamic Pages with Nuxt.js
When we were building a product page, we named our folder with brackets to make that page dynamic. Now when we click on the product card we are redirected to the shop page with the product ID in the URL, that's because Nuxt is replacing "product" inside the folder name with its ID, but our page is still static. To change that we need to get the product ID from the URL and then fetch product data from the server with that ID.
We already created functionality for fetching data from the server, now we need to update our Product page. For that, please, open index.vue file inside the [product] folder and import our products store, then add the created hook inside our component where we will get the router parameter and send it as another parameter into the "aGetProductById" action.
created() {
const productId = this.$route.params.product;
this.productsStore.aGetProductById(productId);
}
Also, we need to update our template (title, price, description, image ...) just to render the data received from the server.
Image:
<div class="product-info__image--main">
<img :src="productsStore.gProduct?.image" alt="product image">
</div>
Product Description:
<h1 class="product-info__content--title">{{ productsStore.gProduct?.name }}</h1>
<p class="product-info__content--price">{{ productsStore.gProduct?.price }} $</p>
<p class="product-info__content--description">{{ productsStore.gProduct?.description }}</p>
Now, let's restart the Nuxt dev server and check the result by clicking on different product cards. We should see another product each time.
In this article, we explored the process of fetching and presenting products in a Nuxt.js e-commerce application. We started by configuring the Axios module, which served as the backbone for making API requests to our server.
Keep in mind that these code examples are only the top of the iceberg. Feel free to experiment with advanced approaches, add new features, and optimize your codebase as you improve your e-commerce application to better suit the demands of your customers and company.
If you would need a source code for this tutorial you can get it here.
Top comments (0)