I'm unable to figure out the problem. I'm exporting a function that serves the current authenticated user object (if present). I'm then using this user object to determine the addition of a nav link. This error won't go away no matter how much I've reformed the reference.
This is the function definition @/app/hooks/use-auth-user.ts
'use client';
import {
fetchAuthSession,
fetchUserAttributes,
getCurrentUser,
} from 'aws-amplify/auth';
import { useEffect, useState } from 'react';
export default function UseAuthUser() {
const [user, setUser] = useState<Record<string, any>>();
useEffect(() => {
async function getUser() {
const session = await fetchAuthSession();
if (!session.tokens) {
return;
}
const user = {
...(await getCurrentUser()),
...(await fetchUserAttributes()),
isAdmin: false,
};
const groups = session.tokens.accessToken.payload['cognito:groups'];
// @ts-ignore
user.isAdmin = Boolean(groups && groups.includes('administrators'));
setUser(user);
}
getUser();
}, []);
return user;
}
And Here is the function that I'm referencing it from @/app/lib/menus.ts
import UseAuthUser from '@/app/hooks/use-auth-user';
export function getResourceMenu(): Menu {
const user = UseAuthUser();
let links: Menu = [
{ name: 'Privacy Policy', href: '/privacy' },
{ name: 'Terms & Conditions', href: '/terms-and-conditions' },
{ name: 'Member Portal', href: '/auth/login' },
];
if (user) {
links.push({ name: 'Dashboard', href: '/dashboard' });
}
return links;
}
I'm attaching a screenshot of the error here:
Error: (0 , _app_hooks_use_auth_user__WEBPACK_IMPORTED_MODULE_0__.default) is not a function
I'd love some input on where I'm going wrong here because obviously - I am.
I tried to reproduce your issue and stumbled upon a different one. By resolving this one, I could run the code with no issues, which perhaps should solve your issue too.
The issue here is that use-auth-user
hook is marked as a client-only module using use client
. Which means it can be used only within client components.
However, the getResourceMenu()
function in menus.ts
is calling UseAuthUser()
directly, which is being treated as a server code, causing a mismatch.
I moved on and refactored the code to make it run successfully to resolve this particular issue and it seems to resolve yours one as well.
Moving the logic to a client component
Here, UseAuthUser
is called in a client component and the result is handed over to getResourceMenu
instead of a direct hook call inside of getResourceMenu
function.
// src/components/MenuComponent.tsx
'use client'; // Mark this as a client component
import React from 'react';
import UseAuthUser from '@/hooks/use-auth-user';
import { getResourceMenu } from '@/lib/menus';
const MenuComponent = () => {
const user = UseAuthUser(); // Fetch user on the client side
const links = getResourceMenu(user); // Pass user data to getResourceMenu
return (
<nav>
{links.map((link, index) => (
<a key={index} href={link.href}>
{link.name}
</a>
))}
</nav>
);
};
export default MenuComponent;
Changes to getResourceMenu
Just accepting user as an input and apply conditional rendering
export function getResourceMenu(user: any) {
let links = [
{ name: 'Privacy Policy', href: '/privacy' },
{ name: 'Terms & Conditions', href: '/terms-and-conditions' },
];
if (user) {
links.push({ name: 'Dashboard', href: '/dashboard' });
}
return links;
}