使用 URL 参数
编辑页面
了解如何在你的应用中访问和修改路由参数和搜索参数。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
URL 参数包括 路由参数 和 搜索参数。Expo Router 提供了用于访问和修改这些参数的 hooks。
路由参数和搜索参数的区别
路由参数是 URL 路径中定义的动态段,例如 /profile/[user],其中 user 是一个路由参数。它们用于匹配路由。
搜索参数(也称为 query params)是可序列化的字段,可以附加到 URL 上,例如 /profile?extra=info,其中 extra 是一个搜索参数。它们通常用于在页面之间传递数据。
本地与全局 URL 参数
在具有嵌套导航器的应用中,你通常会发现同一时间有 多个页面被挂载。例如,当一个新路由被压入栈时,栈会将上一页和当前页保留在内存中。正因为如此,Expo Router 提供了两个不同的 hooks 来访问 URL 参数:
- useLocalSearchParams:返回当前组件的 URL 参数。它只会在全局 URL 与路由一致时更新。
- useGlobalSearchParams:无论组件如何,都会返回全局 URL。它会在每次 URL 参数变化时更新,并且可能导致组件在后台发生额外更新。
useGlobalSearchParams 和 useLocalSearchParams 这两个 hooks 允许你在组件中访问这些参数,从而获取并使用这两类 URL 参数。
这两个 hooks 的类型定义和使用方式相同。唯一的区别在于它们的更新频率。
下面的示例演示了 useLocalSearchParams 和 useGlobalSearchParams 的区别。它使用如下 app 目录结构:
srcapp_layout.tsxindex.tsx[user].tsx1
Root Layout 是一个栈导航器:
import { Stack } from 'expo-router'; export default function Layout() { return <Stack />; }
2
初始路由会重定向到动态路由 src/app/[user].tsx,并带有 user=evanbacon:
import { Redirect } from 'expo-router'; export default function Route() { return <Redirect href="/evanbacon" />; }
3
动态路由 src/app/[user] 会打印全局和本地 URL 参数(在这里指路由参数)。它还允许通过不同的 路由参数 来推入同一路由的新实例:
import { Text, View } from 'react-native'; import { useLocalSearchParams, useGlobalSearchParams, Link } from 'expo-router'; const friends = ['charlie', 'james'] export default function Route() { const glob = useGlobalSearchParams(); const local = useLocalSearchParams(); console.log("Local:", local.user, "Global:", glob.user); return ( <View> <Text>User: {local.user}</Text> {friends.map(friend => ( <Link key={friend} href={`/${friend}`}> 访问 {friend} </Link> ))} </View> ); }
4
应用启动时,会打印以下日志:
Local: evanbacon Global: evanbacon按下 "Visit charlie" 会将 /[user] 的一个新实例压入栈中,且 user=charlie,并记录以下日志:
# 这条日志来自新屏幕Local: charlie Global: charlie# 这条日志来自第一个屏幕Local: evanbacon Global: charlie按下 "Visit james" 也会产生类似效果:
# 这条日志来自新的 "/james" 屏幕Local: james Global: james# 这条日志来自 "/evanbacon" 屏幕Local: evanbacon Global: james# 这条日志来自 "/charlie" 屏幕Local: charlie Global: james结果:
- 当 URL 路由参数 变化时,
useGlobalSearchParams会让后台屏幕重新渲染。如果过度使用,可能会导致性能问题。 - 全局重新渲染会按栈顺序执行,因此第一个屏幕会先重新渲染,然后才是 user=charlie 屏幕重新渲染。
- 即使全局 URL 路由参数 变化了,
useLocalSearchParams仍保持不变。你可以利用这一行为进行数据获取,以确保当你返回时,上一屏的数据仍然可用。
静态类型化的 URL 参数
useLocalSearchParams 和 useGlobalSearchParams 都可以通过泛型进行静态类型化。下面是 user 路由参数的示例:
import { Text } from 'react-native'; import { useLocalSearchParams } from 'expo-router'; export default function Route() { const { user } = useLocalSearchParams<{ user: string }>(); return <Text>User: {user}</Text>; } // 给定 URL:`/evanbacon` // 返回值如下:{ user: "evanbacon" }
任何搜索参数(例如 ?query=...)都可以选择性地添加类型:
const { user, query } = useLocalSearchParams<{ user: string; query?: string }>(); // 给定 URL:`/evanbacon?query=hello` // 返回值如下:{ user: "evanbacon", query: "hello" }
当与 rest 语法(...)一起使用时,路由参数会以字符串数组返回:
import { Text } from 'react-native'; import { useLocalSearchParams } from 'expo-router'; export default function Route() { const { everything } = useLocalSearchParams<{ everything: string[]; }>(); const user = everything[0]; return <Text>User: {user}</Text>; } // 给定 URL:`/evanbacon/123` // 返回值如下:{ everything: ["evanbacon", "123"] }
任何搜索参数将继续作为单独的字符串返回:
import { Text } from 'react-native'; import { useLocalSearchParams } from 'expo-router'; export default function Route() { const { everything } = useLocalSearchParams<{ everything: string[]; query?: string; query2?: string; }>(); const user = everything[0]; return <Text>用户:{user}</Text>; } // 给定 URL:`/evanbacon/123?query=hello&query2=world` // 返回结果如下:{ everything: ["evanbacon", "123"], query: "hello", query2: "world" }
更新 URL 参数
可以使用命令式 API 中的 router.setParams 函数来更新 URL 参数。更新 URL 参数不会向历史栈中新增任何内容。
下面的示例使用 <TextInput> 来更新搜索参数 q:
import { useLocalSearchParams, router } from 'expo-router'; import { useState } from 'react'; import { TextInput, View } from 'react-native'; export default function Page() { const params = useLocalSearchParams<{ query?: string }>(); const [search, setSearch] = useState(params.query); return ( <TextInput value={search} onChangeText={search => { setSearch(search); router.setParams({ query: search }); }} placeholderTextColor="#A0A0A0" placeholder="搜索" style={{ borderRadius: 12, backgroundColor: '#fff', fontSize: 24, color: '#000', margin: 12, padding: 16, }} /> ); }
下面是一个使用 onPress 事件来更新路由参数 user 的示例:
import { useLocalSearchParams, router } from 'expo-router'; import { Text } from 'react-native'; export default function User() { const params = useLocalSearchParams<{ user: string }>(); return ( <> <Text>User: {params.user}</Text> <Text onPress={() => router.setParams({ user: 'evan' })}>前往 Evan</Text> </> ); }
路由参数与搜索参数的区别
路由参数用于匹配路由,而搜索参数用于在路由之间传递数据。请看下面的结构,其中路由参数用于匹配 user 路由:
srcappindex.tsx[user].tsxuser 是一个 路由参数当 src/app/[user] 路由被匹配时,user 参数会传递给组件,并且绝不会是空值。搜索参数和路由参数可以一起使用,并且可以通过 useLocalSearchParams 和 useGlobalSearchParams hooks 访问:
import { useLocalSearchParams } from 'expo-router'; export default function User() { const { // 路由参数 user, // 一个可选的搜索参数。 tab, } = useLocalSearchParams<{ user: string; tab?: string }>(); console.log({ user, tab }); // 给定 URL:`/bacon?tab=projects`,会打印以下内容: // { user: 'bacon', tab: 'projects' } // 给定 URL:`/expo`,会打印以下内容: // { user: 'expo', tab: undefined } }
每当路由参数发生变化时,组件都会重新挂载。
import { Text } from 'react-native'; import { router, useLocalSearchParams, Link } from 'expo-router'; export default function User() { // 这三种方式都会更改路由参数 `user`,并新增一个用户页面。 return ( <> <Text onPress={() => router.setParams({ user: 'evan' })}>前往 Evan</Text> <Text onPress={() => router.push('/mark')}>前往 Mark</Text> <Link href="/charlie">前往 Charlie</Link> </> ); }
哈希支持
URL 哈希 是 URL 中跟在 # 符号后面的字符串。它通常用于网站中链接到页面的特定部分,但也可以用于存储数据。Expo Router 将哈希视为一个名为 # 的特殊搜索参数。它可以使用与 搜索参数 相同的 hooks 和 API 进行访问和修改。
import { Text } from 'react-native'; import { router, useLocalSearchParams, Link } from 'expo-router'; export default function User() { // 访问哈希 const { '#': hash } = useLocalSearchParams<{ '#': string }>(); return ( <> <Text onPress={() => router.setParams({ '#': 'my-hash' })}>设置一个新的哈希</Text> <Text onPress={() => router.push('/#my-hash')}>使用新的哈希进行推送</Text> <Link href="/#my-hash">带哈希的链接</Link> </> ); }
保留参数
某些 URL 参数会被 Expo Router 和 React Navigation 保留用于内部使用。请避免将以下名称用于你自己的参数,以免发生冲突:
screenparamsinitialstate