useSWR mutate函数在多组件共享状态时未按预期触发重新请求的问题排查
问题原因分析与解决方案
这个问题其实是SWR缓存机制和fetcher共享逻辑导致的小坑,核心原因如下:
- 在
App.js里,你调用useSWR('/get/posts', fetcher)时传入了自定义的fetcher函数,用来处理数据请求; - 但在
ItemList.js中,你调用useSWR('/get/posts')时没有传入任何fetcher,同时你也没有全局配置SWR的默认fetcher。
SWR的缓存是完全基于key来管理的,当多个组件使用同一个key时,SWR会共享这个key对应的缓存条目以及相关配置(包括fetcher)。当ItemList组件初始化后,它会把/get/posts这个key关联的fetcher覆盖为undefined(因为你没传)。这时候你在App中调用mutate({}, true)时,SWR尝试用这个key对应的fetcher重新请求数据,但此时fetcher是undefined,自然无法发起网络请求,也就看不到post.json的请求了。
解决方法
你可以通过以下几种方式修复这个问题:
1. 给ItemList组件传入相同的fetcher
确保所有使用同一个SWR key的组件都使用一致的fetcher,建议把fetcher抽成单独文件复用:
// ItemList.js import React from 'react' import useSWR from 'swr'; // 复用和App中相同的fetcher(或者抽成单独文件导入) const fetcher = async(urlKey) => { const url = 'https://jsonplaceholder.typicode.com/posts'; const response = await fetch(url); const result = await response.json(); return result } function ItemList() { const {data,error} = useSWR('/get/posts', fetcher); return null } export default ItemList
2. 全局配置SWR的默认fetcher
在项目入口文件(比如index.js)中全局配置默认fetcher,这样所有useSWR调用如果没传fetcher,都会使用这个全局配置:
import { SWRConfig } from 'swr' import App from './App'; const fetcher = async(urlKey) => { const url = 'https://jsonplaceholder.typicode.com/posts'; const response = await fetch(url); const result = await response.json(); return result } ReactDOM.render( <SWRConfig value={{ fetcher }}> <App /> </SWRConfig>, document.getElementById('root') )
3. 给不需要请求的组件传入null作为fetcher
如果ItemList只是想读取缓存数据、不需要发起请求,可以传入null作为fetcher,这样不会修改key对应的fetcher配置:
// ItemList.js function ItemList() { // 传入null,仅读取缓存,不触发请求也不覆盖fetcher配置 const {data,error} = useSWR('/get/posts', null); return null }
内容的提问来源于stack exchange,提问作者minwoo
相关产品推荐
相关产品推荐

