After transitioning to Nextjs from React, I found the architecture of Nextjs to be quite different and confusing. In my current project, I am attempting to authorize API CRUD operations using a token stored in a cookie. However, when trying to retrieve the token inside the axiosInstance, it is returning undefined
.
axiosInstance.ts
import axios from 'axios';
import Cookies from 'js-cookie';
const axiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_CLIENT_URL,
withCredentials: true,
});
axiosInstance.interceptors.request.use((config) => {
const token = Cookies.get('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export default axiosInstance;
This is the function for getting staff data from the API.
staffAPIServices.ts
import axiosInstance from '../../axios/axiosInstance';
// Get Staff
export const getStaff = async () => {
try {
const response = await axiosInstance.get('admin/staff');
if (response.data.status) {
return response?.data?.data?.staff;
}
} catch (err: unknown) {
const errorString = err instanceof Error ? err.message : 'Unknown Error';
return err;
}
};
To display the staff data in a table, I have implemented the following code:
import clsx from 'clsx';
import { getStaff } from '@/app/utils/services/staff/staffAPIServices';
export default async function StaffTable({
query,
page,
}: {
query: string;
page: number;
}) {
interface ItemType {
id: number;
name: string;
email: string;
email_verified_at: string;
created_at: string;
updated_at: string;
deleted_at: string;
}
const staff = await getStaff();
return (
<div className="mt-6 flow-root">
<div className="inline-block min-w-full align-middle">
<div className="rounded-lg bg-gray-50 p-2 md:pt-0">
<table className="hidden min-w-full text-gray-900 md:table">
<thead className="rounded-lg text-left text-sm font-normal">
<tr>
<th scope="col" className="px-4 py-5 font-medium sm:pl-6">
ID
</th>
<th scope="col" className="px-3 py-5 font-medium">
Name
</th>
<th scope="col" className="px-3 py-5 font-medium">
Email
</th>
<th scope="col" className="px-3 py-5 font-medium">
Date
</th>
<th scope="col" className="px-2 py-5 font-medium">
Status
</th>
<th scope="col" className="relative py-3 pl-6 pr-3">
<span className="sr-only">Edit</span>
</th>
</tr>
</thead>
<tbody className="bg-white">
{Array.isArray(staff) &&
staff.map((item: ItemType) => (
<tr
key={item.id}
className="w-full border-b py-4 text-sm last-of-type:border-none [&:first-child>td:first-child]:rounded-tl-lg [&:first-child>td:last-child]:rounded-tr-lg [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg"
>
<td className="whitespace-nowrap py-3 pl-6 pr-3">
<p>{item.id}</p>
</td>
<td className="whitespace-nowrap px-3 py-4">{item.name}</td>
<td className="whitespace-nowrap px-3 py-4">
{item.email}
</td>
<td className="whitespace-nowrap px-3 py-4">
{item.created_at}
</td>
<td className="whitespace-nowrap px-3 py-4">
<span
className={clsx(
'flex items-center justify-center rounded-full px-4 py-1',
{
'bg-red-500 text-white': item.deleted_at === null,
'bg-green-500 text-white': item.deleted_at !== null,
},
)}
>
{item.deleted_at ? 'Active' : 'Inactive'}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
I have attempted the following solutions:
- Directly inputting the token string as
Bearer fake-token-12312312
(which worked), but this goes against DRY principles and I have numerous API functions. - Transforming
axiosInstance.ts
andstaffAPIServices.ts
into client-side components using'use client'
. This approach did not yield the desired result. - In reference to a related question on StackOverflow, someone suggested fetching the cookie within the page by converting it into a client-side component. However, Nextjs raised an issue stating "Prevent client components from being async functions."