Next.js中TypeScript版REST API HOC包裹组件后无法读取用户数据
解决Next.js中withUser HOC无法传递user数据的问题
问题分析
你的TS版本HOC存在几个潜在问题导致user数据无法正确传递到页面组件:
- 请求header键名错误:
contentType应改为标准的Content-Type - 错误处理不完整:非401的请求错误会导致user保持初始
null,触发不必要重定向 - 类型定义缺失:大量使用
any会引发TS类型推断异常,且Next.js的getInitialProps上下文未使用正确类型 - 重定向后未终止函数执行:虽调用了
res.end(),但需补充return确保函数不再继续执行
修正后的withUser.tsx代码
import axios, { AxiosError } from "axios"; import { API } from "../config"; import { getCookie } from "../helpers/auth"; import type { NextPage, NextPageContext } from "next"; // 定义用户数据类型,根据实际API返回结构调整 interface User { first_name: string; // 可添加其他字段如last_name、email等 } // 定义HOC注入的props类型 interface WithUserInjectedProps { user: User; token: string; userLinks: string[]; } const withUser = <P extends object>(Page: NextPage<P & WithUserInjectedProps>) => { const WithAuthUser: NextPage<P> = (props) => <Page {...props as P & WithUserInjectedProps} />; WithAuthUser.getInitialProps = async (context: NextPageContext): Promise<P | void> => { const token = getCookie("token", context.req); let user: User | null = null; let userLinks: string[] = []; if (token) { try { const response = await axios.get(`${API}/user`, { headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, }); user = response.data.user; userLinks = response.data.links; } catch (err: unknown) { const error = err as AxiosError; if (error.response?.status === 401) { user = null; } else { console.error("获取用户信息失败:", error); user = null; } } } if (user === null) { // 兼容服务端与客户端重定向 if (context.res) { context.res.writeHead(302, { Location: "/" }); context.res.end(); } else { import("next/router").then(({ default: router }) => router.push("/")); } return; } // 获取页面自身的初始props const pageProps = await Page.getInitialProps?.(context) || {}; return { ...pageProps, user, token, userLinks, } as P; }; return WithAuthUser; }; export default withUser;
修正后的User页面代码
import withUser from "../withUser"; import type { User } from "../withUser"; interface UserPageProps { user: User; } const User = ({ user }: UserPageProps) => ( <div className="flex min-h-screen flex-col items-center justify-center"> {user.first_name} </div> ); export default withUser(User);
关键改进点
- 类型安全:添加明确类型定义,避免
any带来的类型推断问题 - Header规范:修正请求头键名,确保服务器正确解析请求
- 完善错误处理:覆盖非401错误场景,补充客户端重定向逻辑
- 函数终止:重定向后添加
return,避免后续代码执行引发异常 - 泛型支持:使用泛型兼容页面自身props,提升HOC复用性
内容的提问来源于stack exchange,提问作者Jerald Baroro
相关产品推荐
相关产品推荐

