注意:问题的本质是
react-query
和Rails的ActiveJob
之间的关系。
我的应用程序中有一种情况,前端发送更新资源的请求,这会触发异步后台任务。当此任务完成时,它会更新数据库中的资源,并且 UI 需要对该更改做出反应。
以下是一个示例:用户单击按钮来更改课程视频中显示的文本。服务器响应 200 并启动该课程的异步视频生成任务。完成后,它会向 UI 发送通知。但是,当视频生成完成时,useMutation 不会使与该突变相关的查询无效,因为它在收到初始突变请求的 200 响应后就已经这样做了。
我已经实现了一个异步失效系统,其中我的自定义挂钩监视通知更改并在发生更改时触发相关失效。我将在下面分享一些伪代码来解释我的方法。
我的问题是:我是否过度设计了这个机制?有没有更简单的方法来实现这个功能?虽然我当前的系统可以工作,但它感觉过于复杂并且存在边缘情况。我很好奇其他人是否也遇到过类似的问题以及他们是如何解决的。
这就是我运行自定义突变钩子的方式
const { mutate } = useCustomMutation('/resource', { invalidations: ['/resource'] })
这就是它处理异步失效决策的方式:
const useCustomMutation = (url, options) => {
const mutationFn = () => {
// logic that inspects response from server to determine whether mutation has started a background task
// if so, saves it in UI state with invalidations that needs to happen
// something like:
if (resp.hasStartedBackgroundTasks()) {
saveAppState({
asyncTaskId: resp.backgroundTaskId,
runAsyncInvalidation: () => queryClient.invalidateQueries({ queryKey: invalidations })
})
}
}
return useMutation({ mutationFn })
}
然后,在我收到通知的地方,我运行在应用程序状态中设置的异步失效:
useEffect(() => {
if (notifications.includes(appState.asynTasksId}) {
appState.runAsyncInvalidation()
}
}, [notifications])
我认为你走在正确的轨道上,你可以阅读https://tkdodo.eu/blog/using-web-sockets-with-react-query并看看是否可以改进它。也许我只是设置中央
useEffect
订阅来使我们需要的查询无效,而不是花哨于 appState
中的函数。