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
相关产品推荐
相关产品推荐

