我有一个路径/items的加载器,它从API获取大量数据,所以我使用延迟加载器.我希望只有在没有搜索查询参数(即从服务器进行初始提取)时才有条件地呈现<Supense><Await>代码,然后使用已经提取的项并根据搜索查询参数对其进行过滤.

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

处理这种情况的最佳方法是什么?我try 使用useState,Location State(从<Form state>开始),但为了使用已经获取的数据,很难不呈现<Await>.

我是否错过了一个可以在这种情况下使用的有价值的模式?没有一个已经确立的模式似乎太常见了

Update—一个快速的代码示例,使用Form state和Location来初始显示从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-&gt;从API获取(慢请求~3秒)
  2. 提交一个表单(例如搜索输入),该表单使用查询参数(例如search=test)导航
  3. /items?search=test—根据查询参数过滤已经提取的项目,而不是再次提取相同的项目,然后进行过滤>

推荐答案

这里我可能是错的,但我不认为我们可以区分路由之间的差异,仅通过路由级别的搜索参数.

因此,我会try 直接在loader中解决这个问题,并使昂贵的fetch条件化.加载器函数参数有两个属性paramsrequest.您可以将request. url转换为URL对象并判断searchParams是否为非空.如果是,您可以退出或使用一些缓冲值.

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

Reactjs相关问答推荐

如何使用react-router-dom导航到网页中的其他路由?

react 派生状态未正确更新

不同步渲染

for each 子级加载父路由加载器

在React中映射对象数组时,如何正确呈现JSX.Element或React.ReactNode类型?

Reaction路由-如何在布局路由内呈现&q;/:id&q;路由

悬停轴时重新绘制自定义参照线

如何使用 React 获取表单中的所有值?

onChange in useEffect 的最佳实践

Stripe Checkout:是否可以创建不自动续订的订阅?

文本的几个词具有线性渐变 colored颜色 - React native

未捕获的类型错误:useSelector 不是函数

如何在对话素材ui中设置边框半径?

Reactjs 表单未反映提交时的更改

将路径数组传递给Route会引发错误

在 Reactjs 中状态发生变化时渲染一个新组件而不替换旧组件

Cypress - 在继续之前等待下一个按钮重新出现

如何在 NavBar 中设置动态标题

react / firebase 基地.如何在我的项目中保存更新的数据?

a.active 类在导入 x.scss 文件时有效,但在使用 x.module.scss 时无效