React/Next.js中useSWR首次点击搜索API返回undefined问题
根本原因
这个问题和React的渲染机制、useSWR的异步请求逻辑直接相关,有两个核心诱因:
- React组件每次渲染产生的状态都是快照,你在点击事件回调中拿到的
data,是点击发生时当前已经完成的渲染周期里的旧值,不会同步等待接口请求返回后再更新。 - useSWR发起请求是异步行为:你点击按钮执行
setShouldFetch(true)后,首先要等React批量更新状态触发组件重渲染,useSWR才会识别到新的key、发起接口请求,等请求成功后会再次触发组件重渲染,data才会被赋值为接口返回值。你在点击回调里直接同步打印data时,上述流程还没走完,第一次点击时data还是初始的undefined,第二次点击时打印的是第一次请求完成后更新的data值,所以看起来是第二次点击才拿到结果。
问题复现截图:
解决方案
方案1:监听data变化处理返回结果
不要在点击回调里直接打印/处理data,通过useEffect监听data的变化,等请求完成data更新后再执行后续逻辑:
// 在组件内添加以下逻辑 useEffect(() => { // 可在这里处理请求返回结果,比如打印、渲染、存到其他状态等 if (data) { console.log('接口返回数据:', data); } }, [data]);
点击回调里只保留触发请求的逻辑即可:
<button onClick={() => { setShouldFetch(true); console.log('当前搜索词:', searchTerm); }} > Search! </button>
方案2:优化请求触发逻辑(更符合SWR的使用习惯)
可以去掉shouldFetch状态,用专门的查询参数状态控制是否发起请求,避免多次点击的状态冲突:
export default function Home() { const [searchTerm, setSearchTerm] = useState(''); // 仅在点击搜索时更新该状态,触发SWR发起请求 const [activeQuery, setActiveQuery] = useState(null); const fetcher = (url) => fetch(url).then((res) => res.json()); const { data, error } = useSWR( activeQuery ? `https://eu-central-1.aws.webhooks.mongodb-realm.com/api/client/v2.0/app/lottigully-jjrda/service/movies/incoming_webhook/movies?arg=${activeQuery}` : null, fetcher ); // 监听data变化处理结果 useEffect(() => { if (data) console.log('搜索结果:', data); }, [data]); if (error) return 'An error has occurred.'; return ( <> <main> <div className={style.main_container}> <NavBar /> <Hero /> </div> <div className={style.search_container}> <SearchBar onChange={(e) => setSearchTerm(e.target.value)} /> <button onClick={() => { setActiveQuery(searchTerm); console.log('当前搜索词:', searchTerm); }} > Search! </button> {/* 渲染时必须判断data存在再访问内部属性 */} {data && <div>搜索结果展示:{JSON.stringify(data)}</div>} </div> </main> </> ); }
内容的提问来源于stack exchange,提问作者moemous
相关产品推荐
相关产品推荐

