不带参数(和跳过选项)调用 RTK Query endpoint.select() 的正确方法

Posted

技术标签:

【中文标题】不带参数(和跳过选项)调用 RTK Query endpoint.select() 的正确方法【英文标题】:Proper way to call RTK Query endpoint.select() with no arguments (and skip options) 【发布时间】:2022-01-21 16:46:15 【问题描述】:

我想使用endpoint.select() 函数从缓存的RTK Query 数据中创建选择器,请参阅RTK Advanced Patterns。

文档明确指出,如果没有查询参数,您可以将 undefined 传递给select()(请参阅选择用户数据部分)。

但是,在我的情况下,除非我通过 initiate() 函数触发查询,否则这不起作用。另一方面,当从查询挂钩触发查询时,选择器无法检索缓存数据。

这里的不工作设置非常简单:

export const productsApi = createApi(
  baseQuery: fetchBaseQuery( baseUrl: API.ENDPOINTS.PRODUCTS ),
  reducerPath: 'productsApi',
  endpoints: (builder) => (
    listAllProducts: builder.query(
      query: ()=>'/list',
    ),
  ),
);
export const  useListAllProductsQuery  = productsApi;

然后在 customHook 中我调用 useListAllProducts 钩子:

const 
  data,
 = useListAllProductsQuery(skip:shouldSkip);

最后在选择器中:

export const selectProducts =
  productsApi.endpoints.listAllProducts.select(); //undefined param as docs recommend

潜在的修复:(或者更像是一个 hacky 解决方法): 奇怪的是,我发现如果我将一个参数(又名 cacheKey)传递给 select 函数并将相同的 cacheKey 传递给查询钩子,突然之间星星对齐并且一切正常(尽管文档声明这不是必需的)。所以修改后的代码如下:

// in selector
export const selectProducts =
  productsApi.endpoints.listAllProducts.select('products');

// in hook
const 
  data,
 = useListAllProductsQuery('products');

我想知道是否有人可以就其工作原理提供一些智慧,或者更好的是 推荐在没有 cacheKey 的查询上使用 select 函数的最佳实践(因为文档似乎不正确或过时?)。

我还想指出,在没有参数的情况下调用select() 时,需要一个指示参数的打字稿警告表面。

【问题讨论】:

【参考方案1】:

我不确定您认为文档在哪里声明您不需要参数。

你需要调用select,使用与调用钩子时相同的参数获取该缓存键的选择器 - 所以如果你调用useMyQuery() ,你可以调用select() - 如果你调用useMyQuery(5),你可以调用select(5)来获取缓存键5的选择器。

这些是单独的缓存条目,您需要为每个缓存条目选择一个选择器。

另外,您能否澄清一下“不工作”的确切含义?使用选择器只会为您提供缓存条目,但不会发出请求 - 毕竟您只是从商店中选择。所以在你使用钩子或调度initiate之前,你会得到一个uninitiated缓存条目。

【讨论】:

文档在多个位置声明它(特别是没有参数的查询)。请参阅我引用的“选择用户数据”部分。在我的示例中,我没有 cacheKey,所以我只是调用了不起作用的 select()。我所说的不工作的意思是选择器无法从缓存中返回任何数据。 因此在您的示例中,useMyQuery() 需要变为 useMyQuery('someDummyKey') 并选择(someDummyKey)。在我进行此更改的那一刻,它按预期工作。 如果这是真的,那将是一个错误 - 但老实说,这不太可能,因为useMyQuery() 也只是在内部调用select() 以获得完全相同的选择器。所以我想会有其他事情发生。你能创建一个显示这种行为的 CodeSandbox 吗? 另外,它似乎永远不会返回任何东西 - 它至少应该返回 status: "uninitialized", isUninitialized: true, is...: false 选项必须始终是第二个参数,因此如果您想使用skip 而不是skipToken,则必须调用useMyQuery(undefined, skip: true )。使用undefined 作为参数将与select() 调用一起使用,undefined 并且没有任何参数被认为是相等的

以上是关于不带参数(和跳过选项)调用 RTK Query endpoint.select() 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Apollo GraphQl 分页 - 限制和跳过

如果我使用 Redux Toolkit 和 RTK-Query,需要 thunk 吗?

最大和跳过两个连续整数

RTK Query 使用 getState() 从另一个切片获取状态

RTK Query invalidatesTags 似乎不会每次都删除缓存的数据

多线程增量和跳过 0 没有锁?