This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
了解如何在你的应用中访问和修改路由参数和搜索参数。
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 目录结构:
1
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>;
}
任何搜索参数(例如 ?query=...)都可以选择性地添加类型:
const { user, query } = useLocalSearchParams<{ user: string; query?: string }>();
当与 rest 语法(...)一起使用时,路由参数会以字符串数组返回:
src/app/[...everything].tsx 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>;
}
任何搜索参数将继续作为单独的字符串返回:
src/app/[...everything].tsx 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 参数
可以使用命令式 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 路由:
当 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 });
}
每当路由参数发生变化时,组件都会重新挂载。
import { Text } from 'react-native';
import { router, useLocalSearchParams, Link } from 'expo-router';
export default function 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 保留用于内部使用。请避免将以下名称用于你自己的参数,以免发生冲突:
screen
params
initial
state