You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Next.js抛出WEBPACK_IMPORTED_MODULE不是函数错误的排查

问题分析与解决方案

核心问题

  1. Hook命名违反React规则:自定义Hook必须以use开头,你的函数名是UseAuthUser,不符合规范,React无法正确识别这是一个Hook,会导致调用/导入异常。
  2. 在普通函数中调用React Hook:getResourceMenu是普通工具函数,不是React组件或自定义Hook,违反了Hook的调用规则——Hook只能在组件顶层或其他自定义Hook顶层调用,不能在普通函数、判断、循环内执行。

修复步骤

步骤1:修正Hook命名

修改@/app/hooks/use-auth-user.ts中的函数名,改为符合规范的useAuthUser:

'use client';
import {
    fetchAuthSession,
    fetchUserAttributes,
    getCurrentUser,
} from 'aws-amplify/auth';
import { useEffect, useState } from 'react';

// 改为以use开头的命名
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'];
            user.isAdmin = Boolean(groups && groups.includes('administrators'));
            setUser(user);
        }

        getUser();
    }, []);

    return user;
}

步骤2:调整菜单逻辑的调用位置

由于Hook不能在普通函数中调用,你需要把菜单生成逻辑移到客户端组件中:

// @/app/components/ResourceMenu.tsx
'use client';
import useAuthUser from '@/app/hooks/use-auth-user';

export default function ResourceMenu() {
    const user = useAuthUser();
    const links = [
        { 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 (
        <nav>
            {links.map(link => (
                <a key={link.href} href={link.href}>
                    {link.name}
                </a>
            ))}
        </nav>
    );
}

之后在你的页面或布局组件中导入这个ResourceMenu组件即可使用,而不是调用普通函数getResourceMenu。

替代方案:封装普通异步函数获取用户

如果需要在非组件场景下获取用户信息,可以单独封装一个异步函数,再在组件中调用:

// @/app/hooks/use-auth-user.ts
'use client';
import {
    fetchAuthSession,
    fetchUserAttributes,
    getCurrentUser,
} from 'aws-amplify/auth';
import { useEffect, useState } from 'react';

// 普通异步函数,用于获取用户信息
export async function fetchAuthUser() {
    const session = await fetchAuthSession();
    if (!session.tokens) {
        return null;
    }

    const user = {
        ...(await getCurrentUser()),
        ...(await fetchUserAttributes()),
        isAdmin: false,
    };

    const groups = session.tokens.accessToken.payload['cognito:groups'];
    user.isAdmin = Boolean(groups && groups.includes('administrators'));
    return user;
}

export default function useAuthUser() {
    const [user, setUser] = useState<Record<string, any>>();

    useEffect(() => {
        fetchAuthUser().then(setUser);
    }, []);

    return user;
}

然后在组件中通过useEffect调用这个函数生成菜单:

'use client';
import { fetchAuthUser } from '@/app/hooks/use-auth-user';
import { useState, useEffect } from 'react';

export default function SomeComponent() {
    const [links, setLinks] = useState([
        { name: 'Privacy Policy', href: '/privacy' },
        { name: 'Terms & Conditions', href: '/terms-and-conditions' },
        { name: 'Member Portal', href: '/auth/login' },
    ]);

    useEffect(() => {
        async function loadMenu() {
            const user = await fetchAuthUser();
            if (user) {
                setLinks(prev => [...prev, { name: 'Dashboard', href: '/dashboard' }]);
            }
        }
        loadMenu();
    }, []);

    return (
        <nav>
            {links.map(link => (
                <a key={link.href} href={link.href}>{link.name}</a>
            ))}
        </nav>
    );
}

内容的提问来源于stack exchange,提问作者FevtheDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:54:59