Independent Consultant & Software Architect
Trainer, Speaker, JS/TS Expert
ArchitekturaNaFroncie.pl (ANF)
Warsaw, PL
Roughly 80% of consequences come from 20% of causes
Roughly 80% of FEATURES come from 20% of API
Roughly 80% of consequences come from 20% of causes
class ComponentOrServiceWhatever {
productsHTTP = inject(ProductsHTTPService)
query = injectQuery(() => ({
queryKey: ['products'],
queryFn: () => this.productsHTTP.getProducts(),
}))
}
<ul>
@for (p of query.data(); track p.id) {
<li>{{ p.name }}</li>
}
</ul>
class ComponentOrServiceWhatever {
productsHTTP = inject(ProductsHTTPService)
page = input(1)
nextPage(){ // or whatever
this.page.update(v => v+1)
}
query = injectQuery(() => ({
queryKey: ['products', { page: this.page() }],
queryFn: ({ queryKey }) => {
const [, criteria] = queryKey
return this.productsHTTP.getProducts(criteria)
},
}))
}
Queries + Keys + Mutations
HTML: <button (click)="mutation.mutate(p.id)">REMOVE</button>
TS: class ComponentOrServiceWhatever {
productsHTTP = inject(ProductsHTTPService)
// ... query
mutation = injectMutation((client) => ({
mutationFn: (id: Product['id']) => this.productsHTTP.delete(id),
onSuccess: (result, id) => {
// invalidate ALL queries with product list
client.invalidateQueries({ queryKey: ['products', 'list'] })
// remove query with product details
client.removeQueries({ queryKey: ['products', 'details', id] })
},
}))
}
onSuccess: () => {
// invalidate MATCHING queries?
client.invalidateQueries({ queryKey: ... })
// remove (entirely) MATCHING queries?
client.removeQueries({ queryKey: ... })
// refetch (eagerly) MATCHING queries?
client.refetchQueries({ queryKey: ... })
// reset (to the default state) MATCHING queries?
client.resetQueries({ queryKey: ... })
// cancel MATCHING running queries?
client.cancelQueries({ queryKey: ['products'] })
// locally update (existing) MATCHING queries?
client.setQueryData(queryKey, (oldValue) => newValue)
},
all products
-> ['products']
product filtered by name
-> ['products', { name: 'xyz' }]
product given by ID: 123
-> ['products', 123]
all products (paginated)
-> ['products', 'list']
-> ['products', 'list', { page: 1 }]
product filtered by name
-> ['products', 'list', { name: 'xyz' }]
product filtered and paginated
-> ['products', 'list', { page: 1, name: 'xyz' }]
product given by ID: 123
-> ['products', 'details', 123]
KEY: ['products']
KEY: ['products', 'list']
KEY: ['products', 'list', { page: 1 }]
KEY: ['products', 'list', { page: 1, name: 'xyz' }]
KEY: ['products', 'details', 123]
['products', 'list']
['products', 'list', { page: 1 }]
['products', 'list', { name: 'xyz' }]
['products', 'list', { page: 1, name: 'xyz' }]
['products', 'details', 123]
['products', 'details', 456]