Ang punchline
Nag-a-scale sa mga team ang declarative tags. Hindi ang string-based keys. ‘Yan ang comparison sa isang linya, at ang buong post na ito ang patunay.
Mas maikli, mas magaan, at masarap basahin ang keys ng TanStack Query sa loob ng iisang codebase. Para sa isang feature team na nagmamay-ari ng bawat query, ang key-based API ang halatang pili. Ang tag system ng RTK Query ay nagdadagdag ng seremonya na hindi mo kailangan sa laki na ‘yan.
Ang hugis na umuubra para sa isang team ay nagiging liability kapag tumawid sa boundaries ng mga team. Ang failure mode ay lumilipat mula sa “ayusin bago mag-merge” tungo sa “hanapin mula sa isang support ticket.”
Ang scenario
Nagsi-ship ang dealing team ng isang executeTrade mutation. May getPortfolio query ang portfolio team na nagbabalik ng holdings ng user. Kapag nagtagumpay ang trade, stale na ang portfolio cache, at may kailangang mag-mark dito para sa refetch.
Gamit ang RTK Query tags
Idineklara ng portfolio team kung ano ang hawak ng kanilang query:
getPortfolio: builder.query({
query: (id) => `/portfolio/${id}`,
providesTags: ['Portfolio'],
}),
Idineklara ng dealing team kung ano ang naaapektuhan ng kanilang mutation:
executeTrade: builder.mutation({
query: (order) => ({ url: '/trades', method: 'POST', body: order }),
invalidatesTags: ['Portfolio'],
}),
Kapag nagtagumpay ang mutation, nililibot ng library ang cache nito, hinahanap ang mga query na nagbibigay ng Portfolio tag, at ire-refetch ang mga naka-mount ngayon. Hindi kailanman binabasa ng dealing team ang code ng portfolio. Hindi nila kailangang malaman kung anong query key ang ginagamit ng portfolio o kung anong hugis ang cache entry. Idineklara nila ang intent sa isang categorical level at ang library ang bahalang magkabit nito.
Nakakabit ang parehong team sa string na 'Portfolio'. Ang coupling na ‘yan ay nakatira sa isang shared na tagTypes list na idineklara sa API module, kaya may iisang source of truth ito.
Gamit ang TanStack Query keys
Nag-i-invalidate ang TanStack ayon sa key, hindi ayon sa category. Ganito ang isinulat ng dealing team:
queryClient.invalidateQueries({ queryKey: ['portfolio'] });
Para maging tama ang linyang ‘yan, kailangang alam ng dealing team ang eksaktong hugis ng query key ng portfolio team. Pumupunta sila sa code ng portfolio, hinahanap ang useQuery call, binabasa ang key, at kinokopya ito sa sarili nilang invalidation.
Nakakabit ang mga team sa parehong string na 'portfolio', pero nasa ibang lugar ang coupling. Isa itong magic string sa mutation handler ng dealing team, na walang contract na tumuturo pabalik sa query ng portfolio.
Ano ang nangyayari kapag naghiwalay ang mga team
Parehong resulta ang nabubuo ng dalawang approach kapag nananatiling coordinated ang mga team. Nire-refetch ang naka-cache na portfolio data, nag-a-update ang UI, nakikita ng user ang sariwang holdings. Naghihiwalay ang dalawang approach kapag lumuwag ang coordination.
Tingnan natin ang isang rename. Nagre-refactor ang portfolio team. Nagbago ang domain term. Ang dating tinatawag nilang “portfolio” ay tinatawag na ngayong “holdings” sa buong API, sa docs, at sa pang-araw-araw na wika ng team. Pinalitan nila ang pangalan ng query key:
// before
useQuery({ queryKey: ['portfolio', accountId], queryFn: fetchPortfolio });
// after
useQuery({ queryKey: ['holdings', accountId], queryFn: fetchHoldings });
Nag-ship sila.
Sa RTK Query na mundo na may tags, walang epekto ang rename sa invalidation ng dealing team. Independent ang tags sa query keys. Ang query ng portfolio team ay nagbibigay pa rin ng 'Portfolio'. Ang mutation ng dealing team ay nag-i-invalidate pa rin ng 'Portfolio'. Buo pa rin ang wiring.
Sa TanStack Query na mundo na may keys, tahimik na sinisira ng rename ang dealing team. Ang invalidateQueries({ queryKey: ['portfolio'] }) ay tumutugma na ngayon sa zero na cached queries. Nagtagumpay ang mutation. Hindi naglalabas ng error ang library dahil hindi error ang pagkakita ng zero matches. Nananatiling stale ang portfolio cache ng user hanggang sa lumipat sila palayo at bumalik, o hanggang sa maglabas ng bug ang isang support ticket.
Walang type error. Walang compile failure. Walang runtime exception. Stale na UI sa production.
Saan nakatira ang coupling
Parehong coupling sa pagitan ng dalawang team ang ini-encode ng dalawang approach. Ang pagkakaiba ay kung saan nakatira ang coupling, at kung ano ang lumilitaw kapag nasira ito.
Ikinakabit ng tags ang mga team sa pamamagitan ng isang category name: isang abstract noun na naglalarawan ng uri ng data. Nakatira ito sa isang shared na enum. Ang mga rename ay nangangailangan ng coordination sa enum na ‘yan, at agad na lumilitaw ang rename dahil biglang nagiging invalid ang bawat endpoint na tumutukoy sa lumang pangalan.
Ikinakabit ng keys ang mga team sa pamamagitan ng isang string identifier: ang literal na hugis na kumikilala sa isang cached entry. Nakatira ito kung saan man ito i-type ng isang tao. Hindi nangangailangan ng coordination ang mga rename dahil walang pumipilit nito. Lumilitaw sila kapag tumama sa production ang bug.
Ang gap na ‘yan sa paglitaw ay hindi isang depekto sa disenyo ng TanStack Query. Mas maikli, mas magaan, at bagay na bagay ang key-based API sa isang team na kabisado ang bawat query. Tumitigil ang hugis sa pagkasya kapag ang mga taong nagsusulat ng invalidation at ang mga taong nagsusulat ng query ay tumigil nang maging iisang mga tao.
Ano ang ibig sabihin nito sa praktika
Ilang bagay na makukuha rito.
Kung ang app mo ay iisang team at iisang codebase, halos aesthetic lang ang pagkakaiba. Mas maikli ang key-based API ng TanStack at walang idinadagdag na seremonya. Maliit ang panganib ng tahimik na invalidation drift dahil may buo kang visibility sa bawat query key.
Kung ang app mo ay may maraming team at nagsi-ship sila nang independent, nagsisimula nang mag-compound ang failure mode ng key-based invalidation. Ang refactor ng bawat team ay posibleng tahimik na break para sa kahit sinong ibang team na tumukoy sa kanilang keys. Puwede kang gumawa ng conventions para palambutin ‘yan (query key factories, shared key constants, code review checklists, integration tests sa buong features), pero conventions ‘yan, hindi enforcement: itinatayo mong muli ang ibinibigay sa ‘yo ng tag system nang libre.
Kung maaga ka pa sa isang library choice at nasa abot-tanaw ang federation o multi-team coordination, sulit na maintindihan ang tag system bago maging arbitrary ang pakiramdam ng API shape. Ang pagpili sa pagitan ng dalawang library ay ang pagpili kung anong failure modes ang handa mong tanggapin.
Babalikan ng Module Federation series ang mas malawak na tanong ng state management sa mga independiyenteng na-ship na remote kapag dumating na ang mga state post nito. Kung bago ka sa server-vs-client-state split na ipinapalagay nito, magsimula rito.