Next.js App目录中React Server Components导入错误排查
问题
在现有Next.js应用中搭建了一个测试React Server Components的基础页面:
// src/app/empty/page.tsx import { Footer } from "components/layout/footer/footer"; export default function EmptyPage() { console.log("EmptyPage"); return ( <> <div className="border-white-10% m-2 inline-block border p-2"> <h1>Empty Page</h1> </div> <Footer /> </> ); }
执行next dev并访问http://localhost:3000/empty,页面正常显示且Footer已渲染,但服务器控制台出现如下错误:
./src/hooks/use-client-side-value.ts Attempted import error: 'useEffect' is not exported from 'react' (imported as 'useEffect'). Import trace for requested module: ./src/hooks/use-client-side-value.ts ./src/components/layout/footer/social-buttons.tsx ./src/components/layout/footer/footer.tsx EmptyPage
footer.tsx、social-buttons.tsx和use-client-side-value.ts文件顶部均添加了"use client";指令,理论上可以安全使用useEffect,请问问题出在哪里?
以下是相关组件完整代码:
footer.tsx
"use client"; import React from "react"; import SocialButtons from "./social-buttons"; interface FooterProps { hasLargePadding?: boolean; } export const Footer = ({ hasLargePadding = true }: FooterProps) => { return ( <div className={`px-3 md:px-6 ${hasLargePadding && "lg:px-18"}`} > <SocialButtons /> </div> ); };
social-buttons.tsx
"use client"; import { useClientSideValue } from "hooks/use-client-side-value"; import { isAndroid, isIOS } from "react-device-detect"; import SocialButton from "./social-button"; const SocialButtons = () => { const facebookSchemeUri = useClientSideValue(() => { if (isIOS) return "fb://profile/112142838181341"; if (isAndroid) return "fb://page/112142838181341"; return undefined; }); return ( <div className="flex"> <SocialButton href="https://facebook.com/company" schemeUri={facebookSchemeUri} icon={<img src="/assets/icons/facebook.svg" alt="Facebook" />} /> <SocialButton href="https://instagram.com/company" icon={ <img src="/assets/icons/instagram.svg" alt="Instagram" style={{ marginLeft: 12 }} /> } /> </div> ); }; export default SocialButtons;
use-client-side-value.ts
"use client"; import { useEffect, useState } from "react"; export function useClientSideValue<T>(callback: () => T) { const [clientSideValue, setClientSideValue] = useState<undefined | T>(); useEffect(() => { setClientSideValue(callback()); }, []); return clientSideValue; }
解决方案
1. 升级React版本
Next.js 13+的App Router要求React版本至少为18.2.0,低版本React可能存在客户端Hook导出异常的问题。执行以下命令升级:
npm install react@latest react-dom@latest
2. 确保"use client"指令位置正确
"use client";必须是文件的第一行代码,前面不能有注释、空行或其他内容。如果指令位置不对,文件会被当作Server Component处理,而服务器环境下的React不导出客户端Hook。
3. 修复第三方库的客户端依赖问题
react-device-detect依赖浏览器API,若在服务器端被执行可能触发异常。可以在useClientSideValue的回调中动态导入该库:
const facebookSchemeUri = useClientSideValue(async () => { const { isAndroid, isIOS } = await import("react-device-detect"); if (isIOS) return "fb://profile/112142838181341"; if (isAndroid) return "fb://page/112142838181341"; return undefined; });
同时需要调整useClientSideValue的类型定义以支持异步回调,或者改用纯客户端的检测逻辑。
4. 清除缓存并重启开发服务器
Next.js开发服务器可能缓存了旧的模块依赖,执行以下步骤:
- 停止
next dev服务 - 删除项目根目录下的
.next文件夹和node_modules/.cache目录 - 重新启动
next dev
5. 检查tsconfig.json配置
确保tsconfig.json的模块解析配置正确,避免导入错误:
{ "compilerOptions": { "moduleResolution": "bundler" } }
内容的提问来源于stack exchange,提问作者Anton Khamets
相关产品推荐
相关产品推荐

