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

Next.js中如何用useContext避免子组件重复传递props?

问题描述

最新情况:在<Head>中调用useContext时会出现问题——详见文末

我正尝试构建一个Next.js页面,通过在子元素中使用useContext来避免重复传递props。一直试图避免在_app.tsx中创建该Provider,因为没必要在子组件中创建状态并传递函数props来设置它。

❌ 子元素访问上下文返回null的实现

(特意使用了显式类型定义,看看静态检查是否能发现问题)

页面组件代码 ([slug]/[code].tsx)

// [slug]/[code].tsx
const PageContents: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = ({
  company,
  references,
}) => {
  if (!company) {
    return <>Loading...</>
  }
  const { name } = company

  return (
    <>
      <Head>
        <Metadata />
      </Head>

      <p>Hi { name }!</p>
    </>
  )
}

const Resume: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = (
  props
) => {
  // 🤔 我尝试在这里创建一个父级“层”,让useContext可以正常工作。
  return (
    <CompanyContext.Provider value={props ? props.company : null}>
      <PageContents {...props} />
    </CompanyContext.Provider>
  )
}

export default Resume

// getStaticProps 已省略

上下文定义代码 (context/CompanyContext.tsx)

// context/CompanyContext.tsx
import type { Company } from '@prisma/client'
import type { ReactNode } from 'react'
import { createContext, useContext } from 'react'

export type LightweightCompany = Omit<Company, 'png' | 'resumeMessage'>
const CompanyContext = createContext<LightweightCompany | null>(null)

export const useCompany = () => {
  const currentCompanyContext = useContext(CompanyContext)

  if (!currentCompanyContext) {
    throw new Error(
      'useCompany has to be used within <CompanyContext.Provider>'
    )
  }

  return currentCompanyContext
}


// 🤔 我不确定是否需要这个;
//    我见过这个模式被广泛使用,
//    但不知道它对我的用例有多大帮助
export function CompanyProvider({
  value,
  children,
}: {
  value: LightweightCompany
  children: ReactNode
}) {
  return (
    <CompanyContext.Provider value={value}>{children}</CompanyContext.Provider>
  )
}
export default CompanyContext

子组件代码 (components/Metadata.tsx)

// components/Metadata.tsx

// 这是我希望避免传递{...props}的众多页内组件之一
// 如果可能的话。

export default function Metadata() {
  const { color, name } = useCompany()
  // useCompany 在这里抛出错误 ❌
}

我想知道是否有遗漏(或误用)的设计模式,可以让代码保持相对简洁/低冗余,同时正常传递上下文。

尝试过的方案:HOC/柯里化

HOC代码 (context/Company.tsx)

// context/Company.tsx
const withCompany = (Component: React.FC<PageProps>) => (props: PageProps) =>
  (
    <CompanyContext.Provider value={props.company}>
      <Component {...props} />
    </CompanyContext.Provider>
  )

页面使用HOC (page.tsx)

// page.tsx

export default withCompany(Page)

更新内容

  • 更新1:做极简示例时能正常工作。
  • 更新2:把代码从<Head>中移出后,功能恢复正常,这似乎是Next.js的问题?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:30:55