首页指南参考教程

使用 URL 参数

了解如何访问和修改应用中的路由和搜索参数。


URL 参数包括路由参数和搜索参数。Expo Router 提供了用于访问和修改这些参数的钩子。

¥URL parameters include both route parameters and search parameters. Expo Router provides hooks for accessing and modifying these parameters.

路由和搜索参数之间的区别

¥Difference between route and search parameters

路由参数是在 URL 路径中定义的动态段,例如 /profile/[user],其中 user 是路由参数。它们用于匹配路由。

¥Route parameters are dynamic segments defined in a URL path, such as /profile/[user], where user is a route parameter. They are used to match a route.

搜索参数(也称为查询参数)是可序列化的字段,可以附加到 URL,例如 /profile?extra=info,其中 extra 是搜索参数。它们通常用于在页面之间传递数据。

¥Search parameters (also known as query params) are serializable fields that can be appended to a URL, such as /profile?extra=info, where extra is a search parameter. They are commonly used to pass data between pages.

本地与全局 URL 参数

¥Local versus global URL parameters

在嵌套应用中,你通常会同时安装多个页面。例如,当推送新路由时,堆栈在内存中具有前一页和当前页。因此,Expo Router 提供了两个不同的钩子来访问 URL 参数:

¥In nested apps, you'll often have multiple pages mounted at the same time. For example, a stack has the previous page and current page in memory when a new route is pushed. Because of this, Expo Router provides two different hooks for accessing URL parameters:

  • 使用本地搜索参数:返回当前组件的 URL 参数。仅当全局 URL 符合路由时才会更新。

    ¥useLocalSearchParams: Returns the URL parameters for the current component. It only updates when the global URL conforms to the route.

  • 使用全局搜索参数:无论组件如何,都返回全局 URL。它会在每个 URL 参数更改时更新,并可能导致组件在后台额外更新。

    ¥useGlobalSearchParams: Returns the global URL regardless of the component. It updates on every URL param change and might cause components to update extraneously in the background.

钩子 useGlobalSearchParamsuseLocalSearchParams 允许你在组件中访问这些参数,使你能够检索和使用两种类型的 URL 参数。

¥The hooks useGlobalSearchParams and useLocalSearchParams allow you to access these parameters within your components, enabling you to retrieve and utilize both types of URL parameters.

两个钩子的键入和访问方式相同。但是,唯一的区别是更新频率。

¥Both hooks are typed and accessed the same way. However, the only difference is how frequently they update.

下面的示例演示了 useLocalSearchParamsuseGlobalSearchParams 之间的区别。它使用以下应用目录结构:

¥The example below demonstrates the difference between useLocalSearchParams and useGlobalSearchParams. It uses the following app directory structure:

app
_layout.tsx
index.tsx
[user].tsx

1

根布局是一个堆栈导航器:

¥The Root Layout is a stack navigator:

app/_layout.tsx
import { Stack } from 'expo-router';

export default function Layout() {
  return <Stack />;
}

2

初始路由重定向到动态路由 app/[user].tsx,其中 user=evanbacon:

¥The initial route redirects to the dynamic route app/[user].tsx, with user=evanbacon:

app/index.tsx
import { Redirect } from 'expo-router';

export default function Route() {
  return <Redirect href="/evanbacon" />;
}

3

动态路由 app/[user] 打印出全局和本地 URL 参数(在本例中为路由参数)。它还允许使用不同的路由参数推送相同路由的新实例:

¥The dynamic route app/[user] prints out the global and local URL parameters (route parameters, in this case). It also allows for pushing new instances of the same route with different route parameters:

app/[user].tsx
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}`}>
          Visit {friend}
        </Link>
      ))}
    </View>
  );
}

4

当应用启动时,会打印以下日志:

¥When the app starts, the following log is printed:

Terminal
Local: evanbacon Global: evanbacon

按 "拜访查理" 会推送带有 user=charlie 的 /[user] 新实例,并记录以下内容:

¥Pressing "Visit charlie" pushes a new instance of /[user] with user=charlie, and logs the following:

Terminal
# This log came from the new screenLocal: charlie Global: charlie# This log came from the first screenLocal: evanbacon Global: charlie

按 "拜访詹姆斯" 也有类似的效果:

¥Pressing "Visit james" has a similar effect:

Terminal
# This log came from the new, "/james" screenLocal: james Global: james# This log came from the "/evanbacon" screenLocal: evanbacon Global: james# This log came from the "/charlie" screenLocal: charlie Global: james

结果:

¥Results:

  • 当 URL 路由参数发生变化时,useGlobalSearchParams 会使背景屏幕重新渲染。如果过度使用,可能会导致性能问题。

    ¥useGlobalSearchParams made the background screens re-render when the URL route parameters changed. It can cause performance issues if overused.

  • 全局重新渲染按照堆栈顺序执行,因此首先重新渲染第一个屏幕,然后重新渲染 user=charlie 屏幕。

    ¥Global re-renders are executed in order of the stack, so the first screen is re-rendered first, then the user=charlie screen is re-rendered after.

  • 即使全局 URL 路由参数发生变化,useLocalSearchParams 也保持不变。你可以利用此行为来获取数据,以确保返回时前一屏幕的数据仍然可用。

    ¥useLocalSearchParams remained the same, even when the global URL route parameters changed. You can leverage this behavior for data fetching to ensure the previous screen's data is still available when you navigate back.

静态类型的 URL 参数

¥Statically-typed URL parameters

useLocalSearchParamsuseGlobalSearchParams 都可以使用泛型进行静态类型化。以下是 user 路由参数的示例:

¥Both the useLocalSearchParams and useGlobalSearchParams can be statically typed using a generic. The following is an example for the user route parameter:

app/[user].tsx
import { Text } from 'react-native';
import { useLocalSearchParams } from 'expo-router';

export default function Route() {
  const { user } = useLocalSearchParams<{ user: string }>();

  return <Text>User: {user}</Text>;
}

// Given the URL: `/evanbacon`
// The following is returned: { user: "evanbacon" }

任何搜索参数(例如,?query=...)都可以随意输入:

¥Any search parameters (for example, ?query=...) can be typed optionally:

app/[user].tsx
const { user, query } = useLocalSearchParams<{ user: string; query?: string }>();

// Given the URL: `/evanbacon?query=hello`
// The following is returned: { user: "evanbacon", query: "hello" }

与 rest 语法 (...) 一起使用时,路由参数将作为字符串数组返回:

¥When used with the rest syntax (...), route parameters are returned as a string array:

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>;
}

// Given the URL: `/evanbacon/123`
// The following is returned: { everything: ["evanbacon", "123"] }

任何搜索参数将继续作为单独的字符串返回:

¥Any search parameters will continue to be returned as individual strings:

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: {user}</Text>;
}

// Given the URL: `/evanbacon/123?query=hello&query2=world`
// The following is returned: { everything: ["evanbacon", "123"], query: "hello", query2: "world" }

更新 URL 参数

¥Updating URL parameters

可以使用命令式 API 中的 router.setParams 函数更新 URL 参数。更新 URL 参数不会将任何新内容推送到历史记录堆栈。

¥URL parameters can be updated using the router.setParams function from the imperative API. Updating a URL parameter will not push anything new to the history stack.

以下示例使用 <TextInput> 更新搜索参数 q:

¥The following example uses a <TextInput> to update the search parameter q:

app/search.tsx
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="Search"
      style={{
        borderRadius: 12,
        backgroundColor: '#fff',
        fontSize: 24,
        color: '#000',
        margin: 12,
        padding: 16,
      }}
    />
  );
}

以下是使用 onPress 事件更新路由参数用户的示例:

¥Here is an example using an onPress event to update the route parameter user:

app/[user].tsx
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' })}>Go to Evan</Text>
    </>
  );
}

路由参数与搜索参数

¥Route parameters versus search parameters

路由参数用于匹配路由,而搜索参数用于在路由之间传递数据。考虑以下结构,其中路由参数用于匹配用户路由:

¥Route parameters are used to match a route, while search parameters are used to pass data between routes. Consider the following structure, where a route parameter is used to match the user route:

app
index.tsx
[user].tsxuser is a route parameter

app/[user] 路由匹配时,user 参数将传递给组件,并且绝不是 null 值。搜索和路由参数可以一起使用,并且可以通过 useLocalSearchParamsuseGlobalSearchParams 钩子访问:

¥When the app/[user] route is matched, the user parameter is passed to the component and never a nullish value. Both search and route parameters can be used together and are accessible with the useLocalSearchParams and useGlobalSearchParams hooks:

app/[user].tsx
import { useLocalSearchParams } from 'expo-router';

export default function User() {
  const {
    // The route parameter
    user,
    // An optional search parameter.
    tab,
  } = useLocalSearchParams<{ user: string; tab?: string }>();

  console.log({ user, tab });

  // Given the URL: `/bacon?tab=projects`, the following is printed:
  // { user: 'bacon', tab: 'projects' }

  // Given the URL: `/expo`, the following is printed:
  // { user: 'expo', tab: undefined }
}

每当更改路由参数时,组件都会重新挂载。

¥Whenever a route parameter is changed, the component will re-mount.

app/[user].tsx
import { Text } from 'react-native';
import { router, useLocalSearchParams, Link } from 'expo-router';

export default function User() {
  // All three of these will change the route parameter `user`, and add a new user page.
  return (
    <>
      <Text onPress={() => router.setParams({ user: 'evan' })}>Go to Evan</Text>
      <Text onPress={() => router.push('/mark')}>Go to Mark</Text>
      <Link href="/charlie">Go to Charlie</Link>
    </>
  );
}

哈希支持

¥Hash support

URL hash 是 URL 中 # 符号后面的字符串。它通常在网站上用于链接到页面的特定部分,但它也可用于存储数据。Expo Router 将哈希值视为使用名称 # 的特殊搜索参数。可以使用 搜索参数 中的相同钩子和 API 来访问和修改它。

¥The URL hash is a string that follows the # symbol in a URL. It is commonly used on websites to link to a specific section of a page, but it can also be used to store data. Expo Router treats the hash as a special search parameter using the name #. It can be accessed and modified using the same hooks and APIs from search parameters.

app/hash.tsx
import { Text } from 'react-native';
import { router, useLocalSearchParams, Link } from 'expo-router';

export default function User() {
  // Access the hash
  const { '#': hash } = useLocalSearchParams<{ '#': string }>();

  return (
    <>
      <Text onPress={() => router.setParams({ '#': 'my-hash' })}>Set a new hash</Text>
      <Text onPress={() => router.push('/#my-hash')}>Push with a new hash</Text>
      <Link href="/#my-hash">Link with a hash</Link>
    </>
  );
}
Expo 中文网 - 粤ICP备13048890号