是否可以为带查询参数和不带查询参数的路径使用不同的加载器,或者在 React Router 6 中添加它们时有条件地跳过加载器?

问题描述 投票:0回答:1

我有一个路径

/items
的加载器,它从 API 获取大量数据,所以我使用延迟加载器。我想仅在没有搜索查询参数(意味着从服务器初始获取)时有条件地渲染
<Supense><Await>
代码,然后使用已获取的项目并根据搜索查询参数过滤它们。

  1. /items
    -> 从 API 获取 3 秒
  2. 提交使用查询参数进行导航的表单(例如搜索输入)(例如
    search=test
  3. /items?search=test
    -> 根据查询参数过滤已获取的项目
    useSearchParams
  • Issue:它重新渲染组件,再次遍历
    <Suspense><Await>

对于这种情况最好的方法是什么?我尝试使用 useState、Location State(来自

<Form state>
),但是很难不渲染
<Await>
来使用已获取的数据。

我是否缺少可以在这种情况下使用的有价值的模式?没有已经建立的模式似乎太常见了

更新 - 使用表单状态和位置的快速代码示例,用于最初显示从 API 获取的项目与根据查询参数过滤的本地保存的项目 (

search
):

装载机功能:

const loader= (() => defer({ itemsAsync: getItems() })) satisfies LoaderFunction; // getItems() is Promise

成分:

const { itemsAsync } = useLoaderData();
const { state: { savedItems } } = useLocation();

const [searchParams] = useSearchParams();
const searchQueryParam = searchParams.get('search')?.toLowerCase() ?? '';

const filterItems = (items: Item[]) => items.filter((item) => item.content.toLowerCase().includes(searchQueryParam));


return state ? (
  <div>
    <Form state={{savedItems: items}}>
      <input type="text" name="search" />
      <input type="submit" hidden />
    </Form>
    {filterItems(state?.items).map((item) => <div>{item}</div>)}
  </div>
) : (
  <Suspense fallback={<div>Loading items...</div>}>
    <Await resolve={itemsAsync}>
      {(items) => (
        <div>
          <Form state={{savedItems: items}}>
            <input type="text" name="search" />
            <input type="submit" hidden />
          </Form>
          {items.map((item) => <div>{item}</div>)}
        </div>
      )}
    </Await>
  </Suspense>
);

提交表单时,它只是添加

search
作为查询参数
/items?search=test
,然后根据测试,我们应该过滤列表并显示所获取项目的子集。由于多种原因,这不起作用 - 例如
search
查询参数仅在加载过程的最后添加到 URL 中,在这种情况下,它从 API 获取新项目(例如 5 秒延迟),然后才进行它会更新实际的 URL。我知道我也可以从加载器的
request
获取参数,但是然后我需要根据是否有参数返回非延迟数据?在使用查询参数时必须有一种更简单的方法来处理“缓存”数据,我现在正在重新发明轮子。

正如我已经提到的,我头脑中的理想流程是:

  1. /items
    -> 从 API 获取(请求缓慢约 3 秒)
  2. 提交使用查询参数进行导航的表单(例如搜索输入)(例如
    search=test
  3. /items?search=test
    -> 根据查询参数过滤已经获取的项目,而不是再次获取相同的项目然后过滤
reactjs react-router react-router-dom
1个回答
0
投票

我在这里可能是错的,但我不认为我们可以区分仅通过路由器级别的搜索参数不同的路由。

因此,我尝试直接在加载器中解决它,并使昂贵的获取成为有条件的。加载器函数参数有两个属性paramsrequest。您可以将 request 属性转换为 URL 对象并检查 searchParams 是否非空。如果是这样,您可以退出或使用一些缓冲值。

function loader({ request }) {
const url = new URL(request.url);
if (url.searchParams.size > 0) return;
// your data fetching

}

© www.soinside.com 2019 - 2024. All rights reserved.