使用 expo-linking API
了解如何在 Expo 的服务器上渲染 React 组件。
实验性地在 SDK 52 及以上版本中可用。这是一个非常早期的预览版,尚未准备好投入生产或广泛使用。此初始版本旨在帮助库作者了解通用 React 服务器组件并在其库中添加支持。
¥Experimentally available in SDK 52 and above. This is a very early preview and not ready for production or wide use yet. This initial version is meant to help library authors understand universal React Server Components and add support in their libraries.
React Server Components 启用了许多令人兴奋的功能,包括:
¥React Server Components enable a number of exciting capabilities, including:
-
使用异步组件和 React Suspense 进行数据提取。
¥Data fetching with async components and React Suspense.
-
使用密钥和服务器端 API。
¥Working with secrets and server-side APIs.
-
用于 SEO 和性能的服务器端渲染 (SSR)。
¥Server-side rendering (SSR) for SEO and performance.
-
构建时渲染以删除未使用的 JS 代码。
¥Build-time rendering to remove unused JS code.
Expo Router 在所有平台上都支持 反应服务器组件。这是 Expo Router 中默认启用的功能的早期预览版。
¥Expo Router enables support for React Server Components on all platforms. This is an early preview of a feature that will be enabled by default in Expo Router.
先决条件
¥Prerequisites
你的项目必须使用 Expo Router 和 React Native 新架构(SDK 52 中的默认架构)。
¥Your project must use Expo Router and React Native new architecture (default in SDK 52).
用法
¥Usage
要在 Expo 应用中使用 React Server Components,你需要:
¥To use React Server Components in your Expo app, you need to:
-
安装所需的 RSC 依赖
react-server-dom-webpack@19.0.0-rc-6230622a1a-20240610
¥Install the required RSC dependency
react-server-dom-webpack@19.0.0-rc-6230622a1a-20240610
-
确保 package.json 中的入口模块是
expo-router/entry
(默认)。¥Ensure the entry module is
expo-router/entry
(default) in package.json. -
在项目应用配置中启用标志:
¥Enable the flag in the project app config:
{
"expo": {
"experiments": {
"reactServerFunctions": true
}
}
}
-
确保应用配置中的任何地方都未设置
"origin": "false"
。¥Ensure
"origin": "false"
is not set anywhere in your app config. -
创建初始路由 app/index.tsx:
¥Create an initial route app/index.tsx:
/// <reference types="react/canary" />
import React from 'react';
import { ActivityIndicator } from 'react-native';
import renderInfo from '../actions/render-info';
export default function Index() {
return (
<React.Suspense
fallback={
// The view that will render while the Server Function is awaiting data.
<ActivityIndicator />
}>
{renderInfo({ name: 'World' })}
</React.Suspense>
);
}
-
创建一个服务器函数 actions/render-info.tsx:
¥Create a Server Function actions/render-info.tsx:
'use server';
import { Text } from 'react-native';
export default async function renderInfo({ name }) {
// Securely fetch data from an API, and read environment variables...
return <Text>Hello, {name}!</Text>;
}
服务器函数的视图返回值是将流式传输到客户端的 React 服务器组件有效负载。
¥The views return value of the Server Function is a React Server Component payload that will be streamed to the client.
在开发者预览期间,应用配置中的
web.output
必须是single
。即将推出对更多输出模式的支持。¥
web.output
must besingle
in the app config during the developer preview. Support for more output modes is coming soon.
设置提供程序
¥Server Components
服务器组件在服务器中运行,这意味着它们可以访问服务器 API 和 Node.js 内置函数(在本地运行时)。它们还可以使用异步组件。
¥Server Components run in the server, meaning they can access server APIs and Node.js built-ins (when running locally). They can also use async components.
考虑以下获取数据并渲染数据的组件:
¥Consider the following component which fetches data and renders it:
import 'server-only';
import { Image, Text, View } from 'react-native';
export async function Pokemon() {
const res = await fetch('https://pokeapi.co/api/v2/pokemon/2');
const json = await res.json();
return (
<View style={{ padding: 8, borderWidth: 1 }}>
<Text style={{ fontWeight: 'bold', fontSize: 24 }}>{json.name}</Text>
<Image source={{ uri: json.sprites.front_default }} style={{ width: 100, height: 100 }} />
{json.abilities.map(ability => (
<Text key={ability.ability.name}>- {ability.ability.name}</Text>
))}
</View>
);
}
要将其渲染为服务器组件,你需要从服务器函数返回它。
¥To render this as a server component, you'll need to return it from a Server Function.
关键点
¥Key points
-
你无法在服务器组件中使用
useState
、useEffect
或useContext
等钩子。¥You cannot use hooks like
useState
,useEffect
, oruseContext
in Server Components. -
你无法在服务器组件中使用浏览器或原生 API。
¥You cannot use browser or native APIs in Server Components.
-
"use server"
并非用于将文件标记为服务器组件。它用于将文件标记为具有从中导出的 React Server Functions。¥
"use server"
is not meant to mark a file as a server component. It's used to mark a file as having React Server Functions exported from it. -
服务器组件可以访问所有环境变量,因为它们安全地从客户端运行。
¥Server components have access to all environment variables as they run securely off the client.
客户端组件
¥Client Components
由于服务器组件无法访问原生 API 或 React 上下文,因此你可以创建客户端组件来使用这些功能。它们是通过在顶部使用 "use client"
指令标记文件来创建的。
¥Since Server Components cannot access native APIs or React Context, you can create a Client Component to use these features. They are created by marking files with the "use client"
directive at the top.
'use client';
import { Text } from 'react-native';
export default function Button({ title }) {
return <Text onPress={() => {}}>{title}</Text>;
}
此模块可以导入并在服务器功能或服务器组件中使用。
¥This module can be imported and used in a Server Function or Server Component.
关键点
¥Key point
你无法将函数作为 props 传递给服务器组件。你只能传递可序列化的数据。
¥You cannot pass functions as props to Server Components. You can only pass serializable data.
接收事件
¥React Server Functions
服务器函数是在服务器上运行的函数,可以从客户端组件调用。将它们视为更易于编写的完全类型的 API 路由。
¥Server Functions are functions that run on the server and can be called from Client Components. Think of them like fully-typed API routes that are easier to write.
它们必须始终是异步函数,并在函数顶部标有 "use server"
。
¥They must always be an async function and are marked with "use server"
at the top of the function.
export default function Index() {
return (
<Button
title="Press me"
onPress={async () => {
'use server';
// This code runs on the server.
console.log('Button pressed');
return '...';
}}
/>
);
}
你可以创建客户端组件来调用服务器函数:
¥You can create a Client Component to invoke the Server Function:
'use client';
import { Text } from 'react-native';
export default function Button({ title, onPress }) {
return <Text onPress={() => onPress()}>{title}</Text>;
}
服务器函数也可以在独立文件中定义(顶部带有 "use server"
)并从客户端组件导入:
¥Server Functions can also be defined in a standalone file (with "use server"
at the top) and imported from Client Components:
'use server';
export async function callAction() {
// ...
}
这些可以在客户端组件中使用:
¥These can be used in a Client Component:
import { Text } from 'react-native';
import { callAction } from './server-actions';
export default function Button({ title }) {
return <Text onPress={() => callAction()}>{title}</Text>;
}
关键点
¥Key points
-
你只能将可序列化的数据作为参数传递给服务器函数。
¥You can only pass serializable data to Server Functions as arguments.
-
服务器函数只能返回可序列化的数据。
¥Server Functions can only return serializable data.
-
服务器函数在服务器上运行,是放置不应暴露给客户端的逻辑的好地方。
¥Server Functions run on the server and are a good place to put logic that should not be exposed to the client.
-
服务器函数目前不能在 DOM 组件内部使用
¥Server Functions currently cannot be used inside of DOM components
渲染路由
¥Rendering in Server Functions
Expo Router 中的 React Server Functions 可以在服务器上渲染 React 组件并流回 RSC 有效负载(React 团队维护的自定义 JSON 格式)以在客户端上渲染。这类似于网络上的服务器端渲染 (SSR)。
¥React Server Functions in Expo Router can render React components on the server and stream back an RSC payload (a custom JSON-like format that's maintained by the React team) for rendering on the client. This is similar to server-side rendering (SSR) on the web.
例如,以下服务器函数将渲染一些文本:
¥For example, the following Server Function will render some text:
'use server';
// Optional: Import "server-only" for sanity.
import 'server-only';
import { View, Image, Text } from 'react-native';
export async function renderProfile({
username,
accessToken,
}: {
username: string;
accessToken: string;
}) {
// NOTE: Rate limits, GDPR, and other server-side operations can be done here.
// Fetch some data securely from an API.
const { name, image } = await fetch(`https://api.example.com/profile/${username}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
// Use secret environment variables securely as this code will live on the server.
// The EXPO_PUBLIC_ prefix is not required here.
'X-Secret': process.env.SECRET,
},
}).then(res => res.json());
// Render
return (
<View>
<Image source={{ uri: image }} />
<Text>{name}</Text>
</View>
);
}
此服务器函数可以从客户端组件调用,内容将流回客户端:
¥This Server Function can be invoked from a Client Component and the contents will be streamed back to the client:
'use client';
import { useLocalSearchParams } from 'expo-router';
import * as React from 'react';
import { Text } from 'react-native';
import { renderProfile } from '@/components/server-actions';
// Loading state that renders while data is being fetched.
function Fallback() {
return <Text>Loading...</Text>;
}
export default function Profile() {
const { username } = useLocalSearchParams();
const { accessToken } = useCustomAuthProvider();
// Call the Server Function with the username and access token.
const profile = React.useMemo(
() => renderProfile({ username, accessToken }),
[username, accessToken]
);
// Render the profile asynchronously with React Suspense and a custom loading state.
return <React.Suspense fallback={<Fallback />}>{profile}</React.Suspense>;
}
库兼容性
¥Library compatibility
并非所有库都针对 React Server Components 进行了优化。你可以使用 "use client"
指令将文件标记为客户端组件并在服务器组件中使用它。这可用于暂时解决兼容性问题。
¥Not all libraries are optimized for React Server Components yet. You can use the "use client"
directive to mark a file as a Client Component and use it in a Server Component. This can be used to temporarily workaround compatibility issues.
例如,考虑一个尚未附带 "use client"
指令的库 react-native-unoptimized
。你可以通过创建模块并重新导出每个模块来解决此问题:
¥For example, consider a library react-native-unoptimized
that does not ship with "use client"
directives yet. You can workaround this by creating a module and re-exporting each module:
// This directive opts the module into client-side rendering.
'use client';
// Re-exporting the imports from the library.
export { One, Two, Three } from 'react-native-unoptimized';
避免使用 export * from '...'
,因为这会破坏服务器和客户端之间交互的一些内部机制。
¥Avoid using export * from '...'
as this breaks some of the internals of interopting between the server and client.
标有 "use client"
的模块无法从服务器组件进行点访问。这意味着如果没有在 react-native
包中进一步优化,StyleSheet.create
或 Platform.OS
等操作将无法在服务器上运行。
¥Modules marked with "use client"
cannot be dot-accessed from Server Components. This means operations like StyleSheet.create
or Platform.OS
will not work on the server without further optimization in the react-native
package.
切换标签
¥Suspense
你可以使用 React Suspense 在等待数据加载时从服务器流回部分 UI。
¥You can stream back partial UI from the server while waiting for data to load by using React Suspense.
在下面的例子中,客户端会立即返回 Loading...
文本,当 <MediumTask>
在一秒钟后完成渲染时,它将用 Medium task done!
替换文本。<ExpensiveTask>
将需要三秒钟才能加载,完成后,它将用 Expensive task done!
替换文本。
¥In the following example, a Loading...
text is returned instantly on the client, and when the <MediumTask>
finishes rendering one second later, it will replace the text with Medium task done!
. The <ExpensiveTask>
will take three seconds to load, and when it finishes, it will replace the text with Expensive task done!
.
import { Suspense } from 'react';
import { renderMediumTask, renderExpensiveTask } from '@/actions/tasks';
export default function App() {
return <Suspense fallback={<Text>Loading...</Text>}>{renderTasks()}</Suspense>;
}
'use server';
export async function renderTasks() {
return (
<Suspense fallback={<Text>Loading...</Text>}>
<>
<MediumTask />
<Suspense fallback={<Text>Loading...</Text>}>
<ExpensiveTask />
</Suspense>
</>
</Suspense>
);
}
async function MediumTask() {
// Wait one second before resolving.
await new Promise(resolve => setTimeout(resolve, 1000));
return <Text>Medium task done!</Text>;
}
async function ExpensiveTask() {
// Wait three seconds before resolving.
await new Promise(resolve => setTimeout(resolve, 3000));
return <Text>Expensive task done!</Text>;
}
如果你删除 <ExpensiveTask>
周围的 Suspense
封装器,你将看到 Loading...
等待两个组件完成渲染后再更新 UI。这使你可以逐步控制加载状态。有时,等待所有内容一次性加载是有意义的(大多数情况下),而其他时候,尽快流回 UI 是有益的(例如 ChatGPT 中的文本响应)。
¥If you remove the Suspense
wrapper around <ExpensiveTask>
, you'll see that the Loading...
waits for both components to finish rendering before updating the UI. This enables you to control the loading state incrementally. Sometimes, it makes sense to wait for everything to load at once (most of the time), while other times, it is beneficial to stream back UI as soon as you have (like the text response in ChatGPT).
秘密
¥Secrets
服务器组件可以访问密钥和服务器端 API。你可以使用 process.env
对象来访问环境变量。你可以通过在项目中导入 server-only
模块来确保模块永远不会在客户端上运行。
¥Server Components can access secrets and server-side APIs. You can use the process.env
object to access environment variables. You can ensure a module never runs on the client by importing the server-only
module in your project.
// This will assert if the module runs on the client.
import 'server-only';
import { Text } from 'react-native';
export async function renderData() {
// This code only runs on the server.
const data = await fetch('https://my-endpoint/', {
headers: {
Authorization: `Bearer ${process.env.SECRET}`,
},
});
// ...
return <div />;
}
你可以在 .env 文件中定义密钥:
¥You can define the secret in your .env file:
SECRET=123
你无需重新启动开发服务器来更新环境变量。它们会在每次请求时自动重新加载。
¥You do not need to restart the dev server to update environment variables. They are automatically reloaded on every request.
平台检测
¥Platform detection
要检测你的代码打包到哪个平台,请使用 process.env.EXPO_OS
环境变量。例如,process.env.EXPO_OS === 'ios'
。最好使用 Platform.OS
,因为 react-native
尚未针对 React Server Components 进行完全优化,无法按预期工作。
¥To detect which platform your code is bundled for, use the process.env.EXPO_OS
environment variable. For example, process.env.EXPO_OS === 'ios'
. Prefer this to Platform.OS
as react-native
is not fully optimized for React Server Components yet and won't work as expected.
你可以通过执行 typeof window === 'undefined'
检查来检测代码是否在服务器上运行。这将始终在客户端设备上返回 true
,在服务器上返回 false
。
¥You can detect if code is running on the server by performing a typeof window === 'undefined'
check. This will always return true
on client devices and false
on the server.
教程:创建原生模块
¥Testing with jest
库作者可以使用 jest-expo
测试他们的模块是否支持服务器组件。在 测试 React 服务器组件 指南中了解更多信息。
¥Library authors can test their modules support Server Components by using jest-expo
. Learn more in the Testing React Server Components guide.
元数据
¥Metadata
React Server Components 是 React 19 的一个功能。要启用它们,Expo CLI 会自动在所有平台上使用 React 的特殊预览版版本。将来,当 React Native 中默认启用 React 19 时,它将被删除。
¥React Server Components are a feature of React 19. To enable them, Expo CLI automatically uses a special canary build of React on all platforms. In the future, it will be removed when React 19 is enabled by default in React Native.
因此,你可以使用 React 19 功能,例如将 <meta>
标签放置在应用的任何位置(仅限网络)。
¥As a result, you can use React 19 features such as placing <meta>
tags anywhere in your app (web-only).
export default function Index() {
return (
<>
{process.env.EXPO_OS === 'web' && (
<>
<meta name="description" content="Hello, world!" />
<meta property="og:image" content="/og-image.png" />
</>
)}
<MyComponent />
</>
);
}
你可以使用它代替 expo-router/head
中的 Head
组件,但目前它仅适用于 Web。
¥You can use this instead of the Head
component from expo-router/head
, but it only works on web for now.
请求查询参数
¥Request headers
你可以使用 expo-router/rsc/headers
模块访问用于向服务器组件发出请求的请求标头。
¥You can access the request headers used to make the request to the Server Component using the expo-router/rsc/headers
module.
import { unstable_headers } from 'expo-router/rsc/headers';
export async function renderHome() {
const authorization = (await unstable_headers()).get('authorization');
return <Text>{authorization}</Text>;
}
unstable_headers
函数返回一个解析为只读 Headers
对象的 promise。
¥The unstable_headers
function returns a promise that resolves to a read-only Headers
object.
关键点
¥Key points
-
此 API 不能与构建时渲染 (
render: 'static'
) 一起使用,因为标头会根据请求动态更改。将来,如果输出模式为static
,此 API 将断言。¥This API cannot be used with build-time rendering (
render: 'static'
) because the headers dynamically change based on the request. In the future, this API will assert if the output mode isstatic
. -
unstable_headers
仅适用于服务器,不能在客户端上使用。¥
unstable_headers
is server-only and cannot be used on the client.
完整 React Server Components 模式
¥Full React Server Components mode
此模式更具实验性!
¥This mode is even more experimental!
启用完整的 React Server Components 支持可让你利用更多功能。在此模式下,路由的默认渲染模式是服务器组件而不是客户端组件。它仍在开发中,因为需要重写 Router 和 React Navigation 以支持并发。
¥Enabling full React Server Components support allows you to leverage even more features. In this mode, the default rendering mode for routes is server components instead of client components. It is still in development, as the Router and React Navigation need to be rewritten to support concurrency.
要启用完整的服务器组件模式,你需要在应用配置中启用 reactServerComponentRoutes
标志:
¥To enable full Server Components mode, you need to enable the reactServerComponentRoutes
flag in the app config:
{
"expo": {
"experiments": {
"reactServerFunctions": true,
"reactServerComponentRoutes": true
}
}
}
启用此功能后,所有路由将默认渲染为服务器组件。将来,这将减少服务器/客户端瀑布流并启用构建时渲染以提供更好的离线支持。
¥With this enabled, all routes will render as Server Components by default. In the future this will reduce server/client waterfalls and enable build-time rendering to provide better offline support.
-
目前没有堆栈路由。自定义布局
Stack
、Tabs
和Drawer
尚不支持服务器组件。¥There is currently no stack routing. The custom layouts,
Stack
,Tabs
, andDrawer
, do not support Server Components yet. -
大多数
Link
组件属性尚不受支持。¥Most
Link
component props are not supported yet.
在服务器功能中渲染
¥Reloading Server Components
这仅限于完整的 React Server Components 模式。
¥This is limited to full React Server Components mode.
服务器组件在开发中的每个请求上都会重新加载。这意味着你可以对服务器组件进行更改,并立即在客户端运行时看到它们。你可能希望以编程方式手动触发重新加载事件以重新获取数据或重新渲染组件。这可以使用 useRouter
钩子中的 router.reload()
函数来完成。
¥Server Components are reloaded on every request in development. This means that you can make changes to your server components and see them reflected immediately in the client runtime. You may want to manually trigger a reload event programmatically to refetch data or re-render the component. This can be done using the router.reload()
function from the useRouter
hook.
'use client';
import { useRouter } from 'expo-router';
import { Text } from 'react-native';
export function Button() {
const router = useRouter();
return (
<Text
onPress={() => {
// Reload the current route.
router.reload();
}}>
Reload current route
</Text>
);
}
如果路由是在构建时渲染的,则不会在客户端上重新渲染。这是因为渲染代码不包含在生产服务器中。
¥If the route was rendered at build-time, it will not be re-rendered on the client. This is because the rendering code is not included in the production server.
构建时渲染
¥Build-time rendering
这仅限于完整的 React Server Components 模式。
¥This is limited to full React Server Components mode.
Expo Router 支持两种不同的服务器组件渲染模式:构建时渲染和请求时渲染。可以使用 unstable_settings
导出在每个路由上指示这些模式:
¥Expo Router supports two different modes of rendering Server Components: build-time rendering and request-time rendering. These modes can be indicated on a per-route basis by using the unstable_settings
export:
import { Text, View } from 'react-native';
export const unstable_settings = {
// This component will be rendered at build-time and never re-rendered in production.
render: 'static',
};
export default function Index() {
return (
<View>
<Text>Hello, world!</Text>
</View>
);
}
-
render: 'static'
将在构建时渲染组件,并且永远不会在生产中重新渲染它。这类似于经典静态站点生成器的工作方式。¥
render: 'static'
will render the component at build-time and never re-render it in production. This is similar to how classic static site generators work. -
render: 'dynamic'
将在请求时渲染组件,并在每次请求时重新渲染它。这类似于服务器端渲染的工作方式。¥
render: 'dynamic'
will render the component at request-time and re-render it on every request. This is similar to how server-side rendering works.
如果你想要客户端渲染,请将数据提取移动到客户端组件并在本地控制渲染。
¥If you want client-side rendering, move your data fetching to a Client Component and control the rendering locally.
标有 static
输出的路由将在构建时渲染并嵌入到原生二进制文件中。这使得无需发出服务器请求即可渲染路由(因为服务器请求是在下载应用时发出的)。
¥Routes marked with static
output will be rendered at build-time and embedded in the native binary. This enables rendering routes without making a server request (because the server request was made when the app was downloaded).
当前默认为 dynamic
渲染。将来,我们将更改缓存和优化,使其更智能、更自动化。
¥The current default is dynamic
rendering. In the future, we'll change the caching and optimizations to be smarter and more automatic.
你可以使用 generateStaticParams
函数在构建时生成静态页面。这对于只能在构建时运行而不是在服务器上运行的组件很有用。
¥You can generate static pages at build-time with the generateStaticParams
function. This is useful for components that must only run at build-time and not on the server.
import { Text } from 'react-native';
// Adding `unstable_settings.render: 'static'` will prevent this component from running on the server.
export const unstable_settings = {
render: 'static',
};
// This function will generate static pages for each shape.
export async function generateStaticParams() {
return [{ shape: 'square' }];
}
export default function ShapeRoute({ shape }) {
return <Text>{shape}</Text>;
}
CSS
这仅限于完整的 React Server Components 模式。
¥This is limited to full React Server Components mode.
Expo Router 支持在服务器组件中导入全局 CSS 和 CSS 模块。
¥Expo Router supports importing global CSS and CSS modules in Server Components.
import './styles.css';
import styles from './styles.module.css';
export default function Index() {
return <div className={styles.container}>Hello, world!</div>;
}
CSS 将从服务器提升到客户端包中。
¥The CSS will be hoisted into the client bundle from the server.
部署
¥Deployment
避免在生产中使用通用服务器组件,因为它们尚不稳定。我们将在未来将所有这些简化为单个命令。
¥Avoid using universal Server Components in production as they are not stable yet. We'll streamline all of this to a single command in the future.
Web
首先,构建 Web 项目:
¥First, build the web project:
-
npx expo export -p web
然后你可以使用 npx expo serve
在本地托管它或将其部署到云端:
¥Then you can host it locally with npx expo serve
or deploy it to the cloud:
EAS Hosting 是部署 Expo API 路由和服务器的最佳方式。
原生
¥Native
你可以按照服务器部署指南实验性地部署原生 React 服务器组件:
¥You can experimentally deploy your native React Server Components by following the server deployment guide:
部署版本化服务器并将其链接到生产原生应用。
已知的限制
¥Known limitations
这是我们正在积极开发的非常早期的技术预览版。
¥This is a very early technical preview that we're actively developing.
-
Expo Snack 不支持打包服务器组件。
¥Expo Snack does not support bundling Server Components.
-
EAS 更新尚未与服务器组件配合使用。
¥EAS Update does not work with Server Components yet.
-
DOM 组件目前无法在生产中使用 React 服务器函数。
¥DOM components cannot use React Server Functions in production yet.
-
生产部署受到限制,目前不推荐。
¥Production deployment is limited and not recommended yet.
-
尚不支持服务器将 RSC 有效负载渲染为 HTML。这意味着静态和服务器输出尚未完全工作。
¥Server Rendering RSC payloads to HTML is not supported yet. This means static and server output doesn't fully work yet.
-
generateStaticParams
仅在完整 React Server Components 模式下得到部分支持。¥
generateStaticParams
is only partially supported in full React Server Components mode. -
尚不支持 HTML
form
与服务器功能的集成(这部分会自动运行,但数据未加密)。¥HTML
form
integration with Server Functions is not supported yet (this partially works automatically, but data is not encrypted). -
StyleSheet.create
和Platform.OS
不支持原生。使用标准对象进行样式处理,使用process.env.EXPO_OS
进行平台检测。¥
StyleSheet.create
andPlatform.OS
are not supported on native. Use standard objects for styles andprocess.env.EXPO_OS
for platform detection. -
由于 Hermes 运行时的限制,Hermes 不支持调用其他服务器函数的 React 服务器函数。这可以通过 Static Hermes 解决。
¥React Server Functions that invoke other Server Functions are not supported on Hermes due to a limitation in the Hermes runtime. This may be resolved with Static Hermes.