tanstack-query-entity-graph
v0.2.0
Published
A smart cache invalidation system for TanStack Query that automatically manages query invalidations based on entity relationships.
Readme
TanStack Query Entity Graph 🎯
A smart cache invalidation system for TanStack Query that automatically manages query invalidations based on entity relationships.
🌟 Features
- 📊 Declarative entity relationships
- 🔄 Automatic cache invalidation
- 🧹 Smart cache reset
- 🎯 Type-safe entity configuration
- 🔗 Direct dependency resolution
- 🎨 Simple and intuitive API
- 🔀 Cross-root invalidation support
📦 Installation
npm install tanstack-query-entity-graph🚀 Usage Guide
1. Setting Up Entity Configuration
Define relationships between your entities:
const entityConfig = {
user: {
name: 'user',
invalidate: ['post'], // Entities to invalidate when user is invalidated
reset: ['stats'] // Entities to reset when user is reset
},
post: {
name: 'post',
invalidate: ['comment']
}
};2. Setting Up the Provider
import { EntityQueryClientProvider } from 'tanstack-query-entity-graph';
const queryClient = new QueryClient();
function App() {
return (
<EntityQueryClientProvider
client={queryClient}
entityConfig={entityConfig}
>
<YourApp />
</EntityQueryClientProvider>
);
}3. Use Cases
Basic Usage - Simple Entity Invalidation
useMutation({
mutationFn: updateUser,
meta: {
affects: ['user']
} // Will invalidate 'user' and all its related entities
})Specifying Action Type
useMutation({
mutationFn: updateUser,
meta: {
affects: [{
name: 'user',
action: 'reset' // 'invalidate' or 'reset'
}]
}
})Using Specific Query Key for Main Entity
useMutation({
mutationFn: updateUser,
meta: {
affects: [{
name: 'user',
action: 'invalidate',
queryKey: userKeys.detail({ id: 123 }) // Specific query key for the main entity
}]
}
})Granular Control Over Related Entities
useMutation({
mutationFn: updateUser,
meta: {
affects: [{
name: 'user',
action: 'invalidate',
invalidate: [
{
entity: 'post',
queryKey: postKeys.list({ userId: 123 })
}
],
reset: [
{
entity: 'stats',
queryKey: statsKeys.detail({ userId: 123 })
}
]
}]
}
})Multiple Entities in One Mutation
useMutation({
mutationFn: updateTeam,
meta: {
affects: [
{
name: 'team',
action: 'invalidate'
},
{
name: 'user',
action: 'reset',
queryKey: userKeys.list({ teamId: 123 })
}
]
}
})Complex Configuration Example - User Update Affecting Comments
useMutation({
mutationFn: updateUser,
meta: {
affects: [{
name: 'user',
action: 'invalidate',
queryKey: userKeys.detail({ id: 123 }), // Specific user detail
invalidate: [
{
entity: 'comment',
queryKey: commentKeys.byUser({ userId: 123 }) // All comments need update because they display user's name
}
]
}]
}
})⚠️ Important Notes
- Entity names must be lowercase
- Query keys must start with the entity name
- An entity specified in the main config cannot appear in its own invalidate/reset arrays
- Each entity's dependency is processed only one level deep
🔍 Query Key Format
// ✅ Correct query key format
useQuery(['user', id], fetchUser);
useQuery(['post', 'list'], fetchPosts);
// ❌ Won't be invalidated
useQuery(['userPost', id], fetchPost);
useQuery(['user-post', id], fetchPost);🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📝 License
This project is licensed under the MIT License - see the LICENSE.md file for details.
