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

为何无法通过服务端组件传递的Props初始化客户端组件状态?

问题:服务端组件传值到客户端组件时useState初始化异常

在Next.js场景中,服务端组件读取Cookie并解析JWT得到用户对象,传递给客户端子组件后出现异常:

  • 客户端组件的user Prop能正确打印并渲染完整用户对象{id: 1, name: "John Doe"}
  • 但通过useState(user)初始化的authUser状态始终为{ token: "" }
  • 刷新页面后恢复正常,尝试多种缓存失效策略无效,替换为useMemo(() => user, [user])则能正常获取用户对象

服务端组件代码

import { cookies } from "next/headers";
import jwt from "jsonwebtoken";

import { Inner } from "@/components/inner";

export const Outer = async () => {
  const token = (await cookies().get("jwt")?.value) || "";

  let user: any = {
    token,
  };

  try {
    user = jwt.verify(token, process.env.JWT_SECRET as string);
  } catch {}


  return <Inner user={user} />;
};

客户端组件代码

"use client";

export const Inner = ({ user }: { user?: any }) => {
  console.log(user); // 始终能正确打印用户对象

  const [authUser, setAuthUser] = React.useState(user);

  return (
    <pre className="text-green-200">
      {JSON.stringify({ user, authUser })}
    </pre>
  );
};

原因分析

这是Next.js服务端渲染(SSR)与客户端hydration的时序差异导致的:

  1. 服务端渲染时,组件会先初始化user为{ token: "" },然后异步解析JWT更新user,最终生成包含正确用户数据的HTML
  2. 客户端hydration阶段,React会优先使用预加载JS包中固化的初始状态值(也就是服务端渲染早期的{ token: "" })来初始化useState
  3. 后续user Prop更新时,useState的初始值不会自动同步,因为useState仅在组件首次挂载时读取初始值

解决方案

方案1:用useEffect同步Prop到状态

通过useEffect监听user Prop的变化,实时同步到authUser状态:

"use client";
import React from "react";

export const Inner = ({ user }: { user?: any }) => {
  console.log(user);
  const [authUser, setAuthUser] = React.useState(user);

  React.useEffect(() => {
    setAuthUser(user);
  }, [user]);

  return (
    <pre className="text-green-200">
      {JSON.stringify({ user, authUser })}
    </pre>
  );
};

方案2:用useMemo替代useState(无需修改状态时)

如果authUser仅用于展示或依赖user计算,不需要修改,直接用useMemo更合适,它会跟随user的变化自动更新:

"use client";
import React from "react";

export const Inner = ({ user }: { user?: any }) => {
  console.log(user);
  const authUser = React.useMemo(() => user, [user]);

  return (
    <pre className="text-green-200">
      {JSON.stringify({ user, authUser })}
    </pre>
  );
};

方案3:优化服务端组件的初始化逻辑

调整服务端组件的代码,确保传递给客户端的user是最终解析完成的值,避免传递中间状态:

import { cookies } from "next/headers";
import jwt from "jsonwebtoken";

import { Inner } from "@/components/inner";

export const Outer = async () => {
  const token = (await cookies().get("jwt")?.value) || "";
  let user: any;

  try {
    user = jwt.verify(token, process.env.JWT_SECRET as string);
  } catch {
    user = { token };
  }

  return <Inner user={user} />;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:16:15