如何使用Angular Signals更新TanStack Query的查询参数?
Angular Signals + TanStack Query 筛选参数更新不触发查询的解决方案
问题根源
你当前的实现中,getEntries()方法创建查询时仅获取了labelIds$()的快照值,TanStack Query无法自动感知Angular Signals的后续更新,因此即使labels$变化,查询也不会重新触发。此外,labelIds$返回的对象结构会导致每次计算生成新对象,可能引发不必要的queryKey误判,同时组件中更新labels$的代码存在属性重复的语法问题。
修正方案
1. 优化信号计算逻辑
将labelIds$改为直接返回逗号分隔的字符串(空数组时返回空字符串),简化后续查询逻辑:
@Injectable() export class FriendsService { #baseUrl = inject(BASE_URL) #http = inject(HttpClient) #query = injectQuery() labels$ = signal<Label[]>([]) // 直接生成逗号分隔的ID字符串,空数组返回空串 labelIds$ = computed(() => this.labels$()?.map(label => label.id).join(',') || '') // ... 后续代码 }
2. 让TanStack Query追踪信号变化
通过将信号直接绑定到查询配置,让TanStack Query感知信号更新:
import { injectQuery } from '@tanstack/angular-query-experimental'; import { firstValueFrom } from 'rxjs'; // ... getEntries() { return this.#query({ // 将signal作为queryKey的一部分,Query会自动追踪其变化 queryKey: ['friends', this.labelIds$], // 用computed信号动态控制查询启用状态 enabled: computed(() => this.labelIds$().length > 0), queryFn: () => { // 获取最新的signal值发起请求 const labelIds = this.labelIds$(); return firstValueFrom( this.#http.get<ListUser[]>(`${this.#baseUrl}/users/friends?labels=${labelIds}`), ); }, retry: 1, }); }
如果你的@tanstack/angular-query-experimental版本不支持直接传入signal到queryKey,可改用computed包装queryKey:
queryKey: computed(() => ['friends', this.labelIds$()]),
3. 修正组件中的更新代码
组件中labels$的更新代码存在对象属性重复问题,应改为:
this.friendService.labels$.set([{id: 1}, {id: 2}])
原理说明
当你将signal或computed signal作为queryKey的一部分时,TanStack Query会自动监听信号的变化。一旦labels$更新,labelIds$会重新计算,queryKey随之变化,Query会识别为新的查询需求并自动触发重新请求。enabled字段使用computed信号,能确保只有当筛选参数非空时才发起请求。
内容的提问来源于stack exchange,提问作者Raphaël Balet
相关产品推荐
相关产品推荐

