由于 TanStack Router 不存储或缓存数据,其在数据突变方面的作用仅限于响应外部突变事件可能产生的 URL 副作用。尽管如此,我们还是整理了一份您可能会发现有用的突变相关功能列表以及实现这些功能的库。
寻找并使用支持以下功能的突变实用工具
一些推荐的库
或者,甚至...
与数据获取类似,突变状态不是一种放之四海而皆准的解决方案,因此您需要选择适合您和您的团队需求的解决方案。我们建议尝试几种不同的解决方案,看看哪种最适合您。
⚠️ 还在吗?提交状态是持久化方面的一个有趣话题。您是否要永远保留每次突变?您如何知道何时删除它?如果用户离开屏幕然后又返回,会怎样?让我们深入探讨一下!
TanStack Router 内置了短期缓存。因此,即使我们在路由匹配项卸载后不存储任何数据,如果进行了任何与 Router 中存储的数据相关的突变,当前路由匹配项的数据很可能就会过时。
当进行与加载器数据相关的突变时,我们可以使用 router.invalidate 来强制 Router 重新加载所有当前路由匹配项
const router = useRouter()
const addTodo = async (todo: Todo) => {
try {
await api.addTodo()
router.invalidate()
} catch {
//
}
}
const router = useRouter()
const addTodo = async (todo: Todo) => {
try {
await api.addTodo()
router.invalidate()
} catch {
//
}
}
所有当前路由匹配项的失效都是在后台进行的,因此在准备好新数据之前,将继续显示现有数据,就像您导航到新路由一样。
如果您想等待失效完成直到所有加载器都完成,请将 {sync: true} 传递给 router.invalidate
const router = useRouter()
const addTodo = async (todo: Todo) => {
try {
await api.addTodo()
await router.invalidate({ sync: true })
} catch {
//
}
}
const router = useRouter()
const addTodo = async (todo: Todo) => {
try {
await api.addTodo()
await router.invalidate({ sync: true })
} catch {
//
}
}
无论使用哪种突变库,突变通常会创建与其提交相关的状态。虽然大多数突变都是“设置即忘”的,但有些突变状态的寿命更长,无论是为了支持乐观 UI 还是为了向用户提供有关其提交状态的反馈。大多数状态管理器会正确地保留此提交状态并公开它,从而能够显示加载微调器、成功消息、错误消息等 UI 元素。
让我们考虑以下交互
如果不将路由更改通知您的突变管理库,则提交状态可能仍然存在,并且当用户返回到之前的屏幕时仍然会看到 **“帖子已成功更新”** 消息。这是不理想的。显然,我们的意图不是要永远保留这个突变状态,对吧?!
希望和假设,最简单的方法是让您的突变库支持一个键控机制,该机制允许在键更改时重置突变的状
const routeApi = getRouteApi('/room/$roomId/chat')
function ChatRoom() {
const { roomId } = routeApi.useParams()
const sendMessageMutation = useCoolMutation({
fn: sendMessage,
// Clear the mutation state when the roomId changes
// including any submission state
key: ['sendMessage', roomId],
})
// Fire off a bunch of messages
const test = () => {
sendMessageMutation.mutate({ roomId, message: 'Hello!' })
sendMessageMutation.mutate({ roomId, message: 'How are you?' })
sendMessageMutation.mutate({ roomId, message: 'Goodbye!' })
}
return (
<>
{sendMessageMutation.submissions.map((submission) => {
return (
<div>
<div>{submission.status}</div>
<div>{submission.message}</div>
</div>
)
})}
</>
)
}
const routeApi = getRouteApi('/room/$roomId/chat')
function ChatRoom() {
const { roomId } = routeApi.useParams()
const sendMessageMutation = useCoolMutation({
fn: sendMessage,
// Clear the mutation state when the roomId changes
// including any submission state
key: ['sendMessage', roomId],
})
// Fire off a bunch of messages
const test = () => {
sendMessageMutation.mutate({ roomId, message: 'Hello!' })
sendMessageMutation.mutate({ roomId, message: 'How are you?' })
sendMessageMutation.mutate({ roomId, message: 'Goodbye!' })
}
return (
<>
{sendMessageMutation.submissions.map((submission) => {
return (
<div>
<div>{submission.status}</div>
<div>{submission.message}</div>
</div>
)
})}
</>
)
}
对于不支持键控机制的库,我们很可能需要在用户离开屏幕时手动重置突变状态。要解决此问题,我们可以使用 TanStack Router 的 invalidate 和 subscribe 方法,在用户不再需要突变状态时清除它们。
router.subscribe
方法是一个将回调函数订阅到各种路由器事件的函数。我们将在这里使用的特定事件是 onResolved
事件。重要的是要理解,当位置路径更改(不仅仅是重新加载)并最终解析时,会触发此事件。
这是重置旧突变状态的好地方。示例如下
const router = createRouter()
const coolMutationCache = createCoolMutationCache()
const unsubscribeFn = router.subscribe('onResolved', () => {
// Reset mutation states when the route changes
coolMutationCache.clear()
})
const router = createRouter()
const coolMutationCache = createCoolMutationCache()
const unsubscribeFn = router.subscribe('onResolved', () => {
// Reset mutation states when the route changes
coolMutationCache.clear()
})
您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。