SWR在组件卸载后还会触发setState吗?
我用SWR请求数据,但在组件卸载后控制台报了警告,说不能在已卸载的组件上执行setState。是不是SWR没处理好取消逻辑?
我试过在useEffect里加了abort controller,但SWR好像有自己的处理机制。下面是我的代码:
import useSWR from 'swr';
function MyComponent() {
const { data, error } = useSWR('/api/user', fetcher);
if (error) return <div>failed to load</div>;
if (!data) return <div>loading...</div>;
return <div>{data.name}</div>;
}
你提到的 abort controller 是一个解决这类问题的好方法,不过 SWR 也提供了一些内置的方式来处理这种情况。你可以尝试使用 SWR 的
useSWRImmutable或者手动控制revalidateOnFocus和revalidateOnReconnect这些选项来避免不必要的重新验证。不过最简单直接的解决办法,还是利用 SWR 提供的
mutate函数的返回值,它会返回一个 promise,我们可以在组件卸载时取消这个 promise。具体可以这样做:这样,在组件卸载的时候,我们可以主动取消掉未完成的请求,从而避免在已卸载的组件上调用 setState。
希望这样能解决你的问题,有时候这些库自带的方法就能完美解决,真是又爱又恨呢。
简单改一下fetcher,加上signal的处理逻辑就行。SWR 2.0+ 会自动把 signal 传给 fetcher。
如果你用的是axios,逻辑也差不多,把signal塞进去。或者如果你不想折腾fetcher,最简单的办法是用SWR官方提供的中间件或者直接用原生fetch,别自己瞎封装,这种坑就少了。
还有一种情况,是你自己在useEffect里监听data变化然后setState,那个记得在useEffect里加个unmounted标记,不过看你的代码应该不是这个问题。先改fetcher试试。