I am having an issue trying to fetch product for my product details page. So far, I have created a product list page full of all of my products which works fine but as soon as I click on the product for product details, either nothing shows or I get a 403 (forbidden) error message. I have tried everything and I cannot get passed this part. Please can someone help me with this?
This is for my product details page:
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import './ProductPage.css';
import '../../App.css';
// GraphQL query to fetch a single product by handle
const fetchProductByHandleQuery = (productId) => `
{
product(handle: "${productId}") {
id
title
descriptionHtml
priceRange {
minVariantPrice {
amount
currencyCode
}
}
images(first: 5) {
edges {
node {
src
}
}
}
}
}
`;
const ProductPage = () => {
const { productId } = useParams();
const [product, setProduct] = useState(null);
useEffect(() => {
// Shopify storefront API Endpoint
const shopifyStoreUrl = `https://<MyShopifyStoreURL/api/2024-10/graphql.json`;
const requestBody = JSON.stringify({
query: fetchProductByHandleQuery(productId),
});
const fetchProductData = async () => {
try {
const response = await fetch(shopifyStoreUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': '',
},
body: requestBody,
});
const data = await response.json();
setProduct(data.data.product);
} catch (error) {
console.log("Error fetching product details", error)
}
}
fetchProductData();
}, [productId]);
if (!product) {
return <div>Loading...</div>; // Show loading state if no product is available
}
if (product.errors) return <div>Product not found.</div>
return (
<div className='product-page-container'>
<h1>{product.title}</h1>
<div className="product-details">
<div className="product-images">
{product.images.edges.map(({ node }) => (
<img key={node.src} src={node.src} alt={product.title} />
))}
</div>
<div className="product-info">
<div dangerouslySetInnerHTML={{ __html: product.descriptionHtml }} />
<p>
<strong>{product.priceRange.minVariantPrice.amount} {product.priceRange.minVariantPrice.currencyCode}</strong>
</p>
<button>Add to Cart</button>
</div>
</div>
</div>
)
}
export default ProductPage;
This is my product list page:
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'
import { fetchProducts } from '../../../../../backend/api/shopifyApi.js'
const Products = () => {
const [productsList, setProductsList] = useState([]);
useEffect(() => {
const getProducts = async () => {
const productData = await fetchProducts();
setProductsList(productData)
};
getProducts();
}, []);
return (
<div className="product-container">
<div className='product-grid'>
{
productsList.map(({ node }) => (
<div
className='product-card'
key={node.id}
>
<Link
to={`/product/${node.productId}`}
reloadDocument
>
{node.images.edges.length > 0 && (
<img
src={node.images.edges[0].node.src}
alt={node.title}
width={300}
/>
)}
{/* <div dangerouslySetInnerHTML={{ __html: node.descriptionHtml }} /> */}
<h2>{node.title}</h2>
</Link>
<p>£{node.variants.edges[0].node.priceV2.amount}</p>
<button type='button'>ADD TO CART</button>
</div>
))
}
</div>
</div>
)
}
export default Products
Can someone please tell me where I am going wrong? Thank you.