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

Next 13.4中RootLayout用Providers触发ReactServerComponentsError问题

解决Next.js 13.4中RootLayout使用Providers触发ReactServerComponentsError并保留metadata的问题

问题原因

RootLayout 是服务器组件,你虽然没给它加"use client",但直接渲染的 Providers 组件里存在未正确处理的客户端逻辑(比如每次渲染都新建 QueryClient 实例),触发了 ReactServerComponentsError;要是错误给 RootLayout 加上"use client",又会导致无法使用 metadata——因为客户端组件不能导出 metadata。

正确解决方案

1. 优化Providers组件的QueryClient创建逻辑

在 Providers 里用 useMemo 缓存 QueryClient 实例,避免每次渲染都重复创建,既能解决错误,还能保证 React Query 的状态稳定:

"use client";

import { useMemo } from "react";
import { ThemeProvider } from "styled-components";
import { SkeletonTheme } from "react-loading-skeleton";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import StyledComponentsRegistry from "@/lib/registry";
import theme from "@/theme";

export function Providers({ children }: { children: React.ReactNode }) {
    // 用useMemo缓存QueryClient,避免重复创建实例
    const queryClient = useMemo(() => new QueryClient(), []);

    return (
        <QueryClientProvider client={queryClient}>
            <StyledComponentsRegistry>
                <ThemeProvider theme={theme}>
                    <SkeletonTheme
                        baseColor="#313131"
                        highlightColor="#525252"
                    >
                        {children}
                    </SkeletonTheme>
                </ThemeProvider>
            </StyledComponentsRegistry>
            <ReactQueryDevtools />
        </QueryClientProvider>
    );
}

2. 保持RootLayout为服务器组件,不要加"use client"

Next.js 13+ 允许服务器组件直接渲染标记了"use client"的客户端组件,所以 RootLayout 不用改,依然能正常导出 metadata:

import "../styles/globals.css";
import { Space_Mono, Work_Sans } from "next/font/google";
import { Providers } from "./providers";
import { Metadata } from "next";

export const space = Space_Mono({
    weight: ["400", "700"],
    subsets: ["latin"],
});

export const work = Work_Sans({
    weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
    display: "fallback", // 避免重载时字体闪烁
    subsets: ["latin"],
});

export const metadata: Metadata = {
    title: "Game-Scope",
    description: "Your one-stop destination for all things gaming.",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <html lang="en">
            <body className={work.className}>
                <Providers>{children}</Providers>
            </body>
        </html>
    );
}

关键说明

  • 服务器组件(比如RootLayout)可以安全渲染客户端组件,只要客户端组件标记了"use client",Next.js会自动处理服务端渲染的占位逻辑。
  • 用useMemo缓存QueryClient是核心修复点,避免了重复创建实例导致的状态异常和渲染错误。
  • 只有服务器组件(或页面组件)能导出metadata,所以必须保持RootLayout的服务器组件身份。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:03:28