SWR:改变数据时立即更新 UI

SWR: immediately update UI when mutating data

我希望 UI 中的数据立即更新,而不是等待 SWR 与数据库同步。

我试过关注 the docs,但 UI 仍然不会自动更新(我切换回浏览器进行更新)。这是代码:

import useSWR, { useSWRConfig } from "swr";

export default function Tasks() {
  const { mutate } = useSWRConfig()
  const { data } = useSWR("/api/tasks", (...args) =>
    fetch(...args).then((res) => res.json())
  )

  const deleteTask = async (taskId) => {
    const newData = data.filter((task) => task.id !== taskId)

    mutate(`/api/tasks/${taskId}`, newData, false)

    await fetch(`/api/tasks/${taskId}`, {
      method: "DELETE",
      headers: {
        "Content-Type": "application/json",
      },
    })

    mutate(`/api/tasks/${taskId}`)
  }

  if (!data) return <p>loading</p>

  return (
    <div>
      {data.map((task) => (
        <div key={task.id}>
          <div>{task.content}</div>
          <button onClick={() => deleteTask(task.id)}>Delete</button>
        </div>
      ))}
    </div>
  )
}

如果您阅读更多文档页面,您可以找到有界变异,它是由 useSWR 钩子返回的函数。这是重新验证数据的最简单方法。 doc

  const { data, mutate } = useSWR('/api/user', fetcher)
  ...
  mutate() //run mutation

问题是您调用了错误的 mutate 函数。当您在 mutate(`/api/tasks/${taskId}`)

上调用 mutate 时,您期望 data 得到刷新

首先进行如下修改

const { data, mutate: mutateList } = useSWR("/api/tasks", (...args) =>
    fetch(...args).then((res) => res.json())
 )

现在,在您的 delete task 中执行以下操作

const deleteTask = async (taskId) => {
    const newData = data.filter((task) => task.id !== taskId)

   // The useSWR("/api/tasks"...) returns a mutate method bound to swr's key, use it! 
   // Passing false will prevent revalidation so a fetch request 
   // won't be made to your api on the other hand if you pass true 
   // then a fetch request will be made to your api. In both cases
   // you should see your cache refreshed immediately and that
   // should update your UI. Since you haven't as yet updated your
   // backend i.e. you are calling mutate _before_ calling your 
   // api, you'll want to pass false as 2nd argument. 
   // Had you called mutate after calling your api then you could 
   // have passed true as second argument to revalidate your cached
   // data. Passing true as second argument in the function below
   // doesn't make sense since you have yet to update your 
   // server/backend.
    await mutateList(newData, false);

    await fetch(`/api/tasks/${taskId}`, {
      method: "DELETE",
      headers: {
        "Content-Type": "application/json",
      },
    })         
}