首页指南参考教程

使用搜索参数

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


搜索参数(也称为查询参数)是可以添加到 URL 的可序列化字段。它们通常用于在页面之间传递数据。Expo Router 提供了用于访问和修改这些参数的钩子。

¥Search parameters (also known as query params) are serializable fields that can be added to a URL. They are commonly used to pass data between pages. Expo Router provides hooks for accessing and modifying these parameters.

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

¥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 search parameters:

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

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

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

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

两个钩子的键入和访问方式相同。但是,唯一的区别是更新频率。考虑以下示例:

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

本地与全局搜索参数

¥Local versus global search parameters

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

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

app
_layout.js
index.js
[user].js

1

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

¥The Root Layout is a stack navigator:

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

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

2

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

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

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

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

3

动态路由 app/[user] 打印出全局和本地搜索参数。它还允许使用不同的搜索参数推送同一路由的新实例:

¥The dynamic route app/[user] prints out the global and local search parameters. It also allows for pushing new instances of the same route with different search parameters:

app/[user].js
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:

  • 当搜索参数更改时,useGlobalSearchParams 使背景屏幕重新渲染。如果过度使用,可能会导致性能问题。

    ¥useGlobalSearchParams made the background screens re-render when the search params 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.

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

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

静态类型的搜索参数

¥Statically-typed search parameters

useLocalSearchParamsuseGlobalSearchParams 都可以使用泛型进行静态类型化:

¥Both the useLocalSearchParams and useGlobalSearchParams can be statically typed using a generic:

app/search.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>;
}

任何其他搜索参数都可以选择输入:

¥Any additional search parameters are to be typed optionally:

const { user, query } = useLocalSearchParams<{ user: string; query?: string }>();

与其余语法 (...) 一起使用时,实现字符串数组:

¥When used with the rest syntax (...), implements a string array:

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

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

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

更新搜索参数

¥Updating search parameters

可以使用命令式 API 中的 router.setParams 函数来更新搜索参数。以下示例使用 <TextInput> 来更新搜索参数 q。此操作不会将任何新内容推送到历史堆栈中。

¥Search parameters can be updated using the router.setParams function from the imperative API. The following example uses a <TextInput> to update the search parameter q. This action will not push anything new to the history stack.

app/search.tsx
import { useLocalSearchParams, router } from 'expo-router';
import React from 'react';
import { TextInput, View } from 'react-native';

export default function Page() {
  const params = useLocalSearchParams<{ q?: string }>();
  const [search, setSearch] = React.useState(params.q);

  return (
    <TextInput
      value={search}
      onChangeText={search => {
        setSearch(search);
        router.setParams({ q: search });
      }}
      placeholderTextColor="#A0A0A0"
      placeholder="Search"
      style={{
        borderRadius: 12,
        backgroundColor: '#fff',
        fontSize: 24,
        color: '#000',
        margin: 12,
        padding: 16,
      }}
    />
  );
}

路由参数与搜索参数

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

当路由参数改变时,组件将重新挂载。

¥When 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号