La conclusió
Les tags declaratives escalen a equips. Les keys basades en strings no. Aquesta és la comparació en una línia, i la resta del post n’és la prova.
Les keys de TanStack Query són més curtes, més lleugeres i agradables de llegir dins d’un sol codebase. Per a un equip de funcionalitat que és propietari de cada query, l’API basada en keys és la tria òbvia. El sistema de tags de RTK Query afegeix una cerimònia que no necessites a aquesta mida.
La forma que funciona per a un equip es converteix en un llast quan travessa les fronteres entre equips. El mode de fallada passa de «arregla-ho abans del merge» a «troba-ho des d’un tiquet de suport».
L’escenari
L’equip de dealing entrega una mutation executeTrade. L’equip de portfolio té una query getPortfolio que retorna les posicions de l’usuari. Quan el trade té èxit, la cache del portfolio està caducada, i alguna cosa ha de marcar-la per refetchar.
Amb les tags de RTK Query
L’equip de portfolio declara què conté la seva query:
getPortfolio: builder.query({
query: (id) => `/portfolio/${id}`,
providesTags: ['Portfolio'],
}),
L’equip de dealing declara què afecta la seva mutation:
executeTrade: builder.mutation({
query: (order) => ({ url: '/trades', method: 'POST', body: order }),
invalidatesTags: ['Portfolio'],
}),
Quan la mutation té èxit, la llibreria recorre la seva cache, troba les queries que proveeixen la tag Portfolio, i refetcha les que estan muntades en aquell moment. L’equip de dealing no llegeix mai el codi de portfolio. No necessiten saber quina query key fa servir portfolio ni quina forma té l’entrada de la cache. Declaren la intenció a un nivell categòric i la llibreria ho connecta.
Tots dos equips estan acoblats al string 'Portfolio'. Aquest acoblament viu en una llista tagTypes compartida i declarada al mòdul de l’API, així que té una sola font de veritat.
Amb les query keys de TanStack Query
TanStack invalida per key, no per categoria. L’equip de dealing escriu:
queryClient.invalidateQueries({ queryKey: ['portfolio'] });
Perquè aquesta línia sigui correcta, l’equip de dealing ha de saber la forma exacta de la query key de l’equip de portfolio. Miren el codi de portfolio, troben la crida a useQuery, llegeixen la key, i la copien a la seva pròpia invalidació.
Els equips estan acoblats al mateix string 'portfolio', però l’acoblament viu en un lloc diferent. És un magic string al handler de la mutation de l’equip de dealing, sense cap contracte que apunti de tornada a la query de portfolio.
Què passa quan els equips es desincronitzen
Tots dos enfocaments produeixen el mateix resultat quan els equips es mantenen coordinats. Les dades del portfolio a la cache es refetchen, la UI s’actualitza, l’usuari veu les posicions actualitzades. Els enfocaments divergeixen quan la coordinació falla.
Posem un rename. L’equip de portfolio està refactoritzant. El terme del domini ha canviat. El que abans anomenaven «portfolio» ara es diu «holdings» a l’API, a la documentació, i al llenguatge del dia a dia de l’equip. Reanomenen la query key:
// before
useQuery({ queryKey: ['portfolio', accountId], queryFn: fetchPortfolio });
// after
useQuery({ queryKey: ['holdings', accountId], queryFn: fetchHoldings });
Ho entreguen.
En un món de RTK Query amb tags, el rename no té cap efecte sobre la invalidació de l’equip de dealing. Les tags són independents de les query keys. La query de l’equip de portfolio segueix proveint 'Portfolio'. La mutation de l’equip de dealing segueix invalidant 'Portfolio'. La connexió aguanta.
En un món de TanStack Query amb keys, el rename trenca l’equip de dealing en silenci. invalidateQueries({ queryKey: ['portfolio'] }) ara coincideix amb zero queries a la cache. La mutation té èxit. La llibreria no mostra cap error perquè trobar zero coincidències no n’és cap. La cache del portfolio de l’usuari es queda caducada fins que l’usuari surt de la pantalla i hi torna, o fins que un tiquet de suport treu el bug a la llum.
Cap error de tipus. Cap fallada de compilació. Cap excepció en runtime. UI caducada en producció.
On viu l’acoblament
Tots dos enfocaments codifiquen el mateix acoblament entre els dos equips. La diferència és on viu l’acoblament, i què apareix quan es trenca.
Les tags acoblen els equips a través d’un nom de categoria: un nom abstracte que descriu una mena de dades. Viu en un enum compartit. Els renames necessiten coordinació a través d’aquest enum, i el rename apareix de seguida perquè tots els endpoints que referencien el nom antic queden invàlids de cop.
Les keys acoblen els equips a través d’un identificador de string: la forma literal que identifica una entrada de la cache. Viu allà on algú l’escriu. Els renames no necessiten coordinació perquè res no els obliga. Apareixen quan el bug arriba a producció.
Aquesta diferència en el moment d’aparèixer no és un defecte del disseny de TanStack Query. L’API basada en keys és més curta, més lleugera, i s’adapta bé a un sol equip que té totes les queries al cap. La forma deixa d’encaixar quan la gent que escriu la invalidació i la gent que escriu la query deixen de ser la mateixa gent.
Què vol dir això a la pràctica
Unes quantes coses per endur-se’n.
Si la teva app és un sol equip i un sol codebase, la diferència és sobretot estètica. L’API basada en keys de TanStack és més curta i no afegeix cap cerimònia. El risc de desincronització silenciosa de la invalidació és petit perquè tens visibilitat total sobre cada query key.
Si la teva app té diversos equips i s’entreguen de forma independent, el mode de fallada de la invalidació basada en keys comença a acumular-se. El refactor de cada equip és una possible ruptura silenciosa per a qualsevol altre equip que hagi referenciat les seves keys. Pots construir convencions per suavitzar-ho (query key factories, constants de key compartides, checklists de revisió de codi, tests d’integració entre funcionalitats), però són convencions, no imposició: estàs reconstruint el que el sistema de tags et dóna de franc.
Si estàs al principi d’una tria de llibreria i tens la federació o la coordinació entre equips a l’horitzó, val la pena entendre el sistema de tags abans que la forma de l’API et sembli arbitrària. Triar entre les dues llibreries vol dir triar amb quins modes de fallada estàs disposat a conviure.
La sèrie de Module Federation reprèn la pregunta més àmplia de la gestió d’estat entre remotes entregats de forma independent quan arribin els seus posts sobre estat. Si ets nou a la distinció entre estat del servidor i estat del client que aquest post dóna per feta, comença aquí.