Just for full context, I am using App Router in next.js.
I am having trouble passing ‘serial_num’ as an argument to my api function “fetchImages” when I am trying to trigger it from inside UseEffect in my page.tsx.
Here is my fetchImages
function:
/app/services/ApiService.js/fetchImages
export async function fetchImages(req, res, serial_num) {
const url = `https://my_long_url/endpoint?serial_num=${serial_num}`;
console.log('Making API call to:', url);
const data = await fetchAuthenticatedData(req, res, url);
return data;
}
So, here is my page.tsx
where I am trying to call this fetchImages
function. Basically, I have a table in my dashboard when ‘View’ button is clicked it renders the following page.
/app/dashboard/[id]/page.tsx/Images
import { fetchImages } from '../../../services/ApiService'
const Images = () => {
// I am getting the serial_num here
const pathname = usePathname();
const serial_num = pathname.split("/").pop();
const [mainImage, setMainImage] = useState("");
const [selectedBlade, setSelectedBlade] = useState(null);
useEffect(() => {
const fetchAndSetImages = async (serial_num) => {
try {
console.log('serial number:', serial_num); // this logs correctly
const data = await fetchImages(serial_num);
const bladesArray = Object.entries(data.images).map(([key, value]) => ({
id: key,
src: `data:image/jpeg;base64,${value}`,
}));
setBlades(bladesArray);
if (bladesArray.length > 0) {
setSelectedBlade(bladesArray[0].id);
setMainImage(bladesArray[0].src);
}
} catch (error) {
console.error('Error fetching images:', error);
}
};
if (serial_num) {
fetchAndSetImages(serial_num);
}
}, [serial_num]);
The serial_num
is being passed as undefined because when I log console.log('Making API call to:', url);
in my fetchImages
function, I get:
Making API call to: https://my-long-url/endpoint?serial_num=undefined
Also, if I explicitly include the serial_num in the function as follows, obviously it works fine:
export async function fetchImages(req, res, serial_num='123') {
const url = `https://my_long_url?serial_num=${serial_num}`;
console.log('Making API call to:', url);
const data = await fetchAuthenticatedData(req, res, url);
return data;
}
async function fetchAuthenticatedData(req, res, url) {
try {
const accessToken = await fetchAccessToken();
const idToken = await fetchIdToken(req, res);
console.log('Making API call to:', url);
const fetchResponse = await fetch(url, {
headers: {
'Content-Type': 'application/json',
'uid': idToken,
Authorization: `Bearer ${accessToken}`,
'cache-control': 'no-cache',
}
});
if (!fetchResponse.ok) {
const errorText = await fetchResponse.text();
console.error('Error response:', errorText);
throw new Error(`HTTP error! status: ${fetchResponse.status}`);
}
const data = await fetchResponse.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
throw error;
}
}
// Function to get the ID token
export const fetchIdToken = async (req, res) => {
const session = await getSession(req, res);
return session?.idToken;
};
Please help me see what I am missing, I am only few weeks into React.
2
Your fetchImages
function expects req
, res
, and serial_num
as parameters. but you’re only passing serial_num
from your useEffect
which will make it difficult to work in a client-side environment except you want to modify your function to either not expect req
and res
or provide dummy values when calling it where you don’t have req
and res
available.
something like this:
export async function fetchImages(serial_num) {
const url = `https://my_long_url/endpoint?serial_num=${serial_num}`;
console.log('Making API call to:', url);
const response = await fetch(url);
const data = await response.json();
return data;
} --- those are for client side
// Calling fetchImages in useEffect
import { fetchImages } from '../../../services/ApiService'
import { useState, useEffect } from 'react';
import { usePathname } from 'next/navigation';
const Images = () => {
const pathname = usePathname();
const serial_num = pathname.split("/").pop();
const [mainImage, setMainImage] = useState("");
const [selectedBlade, setSelectedBlade] = useState(null);
const [blades, setBlades] = useState([]);
useEffect(() => {
const fetchAndSetImages = async (serial_num) => {
try {
console.log('serial number:', serial_num);
const data = await fetchImages(serial_num);
const bladesArray = Object.entries(data.images).map(([key, value])
=> ({
id: key,
src: `data:image/jpeg;base64,${value}`,
}));
setBlades(bladesArray);
if (bladesArray.length > 0) {
setSelectedBlade(bladesArray[0].id);
setMainImage(bladesArray[0].src);
}
} catch (error) {
console.error('Error fetching images:', error);
}
};
if (serial_num) {
fetchAndSetImages(serial_num);
}
}, [serial_num]);
return (
<div>
Your JSX codes
</div>
);
};
export default Images;
1