将 React.Context 与 Nextjs13 服务器端组件结合使用

Tom*_*mog 27 reactjs server-side-rendering next.js react-context

Next13 一周前发布,我正在尝试将 next12 应用程序迁移到 next13。我想尽可能多地使用服务器端组件,但我似乎无法使用

import { createContext } from 'react';
Run Code Online (Sandbox Code Playgroud)

在任何服务器组件中。

我收到此错误:

Server Error
Error: 

You're importing a component that needs createContext. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.

   ,----
 1 | import { createContext } from 'react';
   :          ^^^^^^^^^^^^^
   `----


Maybe one of these should be marked as a client entry with "use client":
Run Code Online (Sandbox Code Playgroud)

这里有其他选择吗?还是我必须诉诸道具钻探来获得服务器端渲染?

Nic*_* Vu 24

这是 React 的 SSR 的一项新功能,用于识别组件是客户端还是服务器端。就您而言,createContext仅在客户端可用。

如果您仅将此组件用于客户端,则可以'use client';在组件之上定义。

'use client';

import { createContext } from 'react';
Run Code Online (Sandbox Code Playgroud)

您可以查看此 Next.js 文档此 React RFC了解详细信息

  • 谢谢,是的,我知道......问题的重点是如何在服务器组件中传递上下文,而不使用“use client” (11认同)

Tom*_*mog 15

看来我可以用createServerContext

import { createServerContext } from 'react';
Run Code Online (Sandbox Code Playgroud)

如果您使用 Typescript 和 React 18,您还需要添加"types": ["react/next"]编译tsconfig.json器选项,因为这是一个尚未稳定的函数。

  • 你使用的是哪个 React 版本?我得到一个“react”没有名为“createServerContext”的导出成员。您的意思是“createContext”吗? (4认同)
  • @Rijk `@types/react` 将此函数归类为“下一个”函数,因此要在 Typescript 中访问它,您需要将 `"types": ["react/next"]` 添加到 `tsconfig 中的 `compilerOptions` 中.json` (3认同)
  • 这已经过时了,你应该使用 React 18 `cache` 函数,它为你处理服务器端的请求范围上下文。 (2认同)
  • ⚠️ ServerContext 已弃用!⚠️ (2认同)

Man*_*dez 11

我制作了一个小包来处理服务器组件中的上下文,与最新的 next.js 一起使用,它被称为server-only-context

https://www.npmjs.com/package/server-only-context

用法:

import serverContext from 'server-only-context';

export const [getLocale, setLocale] = serverContext('en')
export const [getUserId, setUserId] = serverContext('')
Run Code Online (Sandbox Code Playgroud)
import { setLocale, setUserId } from '@/context'

export default function UserPage({ params: { locale, userId } }) {
  setLocale(locale)
  setUserId(userId)
  return <MyComponent/>
}
Run Code Online (Sandbox Code Playgroud)
import { getLocale, getUserId } from '@/context'

export default function MyComponent() {
  const locale = getLocale()
  const userId = getUserId()

  return (
    <div>
      Hello {userId}! Locale is {locale}.
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

这是它的代码,非常简单:

import { getLocale, getUserId } from '@/context'

export default function MyComponent() {
  const locale = getLocale()
  const userId = getUserId()

  return (
    <div>
      Hello {userId}! Locale is {locale}.
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)