You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React使用SWR实现点击按需请求数据缓存时首次赋值异常如何解决

问题根源

  • setState本身是异步批量更新的,你在handleTv中同步调用setShouldFetchTv、setOnTv、setMedia时,更新的状态不会立刻生效,本次函数执行时拿到的还是旧的状态值
  • SWR的请求是异步的,触发shouldFetchTv变为true后,请求不会立刻返回结果,tvResult在第一次点击时还是初始的undefined
  • 你不需要自己实现缓存逻辑,SWR天然支持同key请求缓存,只要请求地址不变,第一次请求后后续都会直接读取缓存,不会重复发起请求,完全匹配你的需求

优化实现方案

你可以直接用一个状态记录当前激活的标签,对应触发对应SWR请求即可,代码简化如下:

import useSWR from 'swr'
import React, { useState } from "react";

const fetcher = async (url) => {
    const res = await fetch(url);
    if (!res.ok) throw new Error('请求失败')
    return res.json()
};
  
const Trending = ({ data: streamingData }) => {
    // 记录当前激活的标签,默认是streaming
    const [activeTab, setActiveTab] = useState('streaming')

    const urls = {
        onTv: `https://api.themoviedb.org/3/tv/on_the_air?api_key=${process.env.NEXT_PUBLIC_API_KEY}&language=en-US&page=1`,
        inTheaters: `https://api.themoviedb.org/3/movie/now_playing?api_key=${process.env.NEXT_PUBLIC_API_KEY}&language=en-US&page=1&region=US`
    }

    // 只有激活onTv标签时才发起请求,SWR自动缓存结果
    const { data: onTvData } = useSWR(activeTab === 'onTv' ? urls.onTv : null, fetcher)
    // 只有激活inTheaters标签时才发起请求
    const { data: inTheatersData } = useSWR(activeTab === 'inTheaters' ? urls.inTheaters : null, fetcher)

    // 根据当前激活标签返回对应展示数据
    const currentMedia = {
        streaming: streamingData,
        onTv: onTvData,
        inTheaters: inTheatersData
    }[activeTab]

    return (
        <div>
            {/* 标签栏 */}
            <div onClick={() => setActiveTab('streaming')}>
                <h1>Streaming</h1>
            </div>
            <div onClick={() => setActiveTab('onTv')}>
                <h1>On Tv</h1>
            </div>
            <div onClick={() => setActiveTab('inTheaters')}>
                <h1>In Theaters</h1>
            </div>

            {/* 数据展示区域,可自定义loading、错误态逻辑 */}
            {currentMedia ? (
                <div>
                    {/* 渲染你的媒体列表数据 */}
                </div>
            ) : <div>加载中...</div>}
        </div>
    )
}

逻辑说明

  • 当第一次点击On Tv标签时,activeTab变为onTv,SWR检测到请求key存在就会发起请求,请求完成后自动更新onTvData,页面自动渲染对应内容
  • 后续再切换到其他标签再切回On Tv时,SWR会直接读取之前缓存的结果,不会重复发起请求
  • 不需要自己维护缓存、是否请求的状态,全部交给SWR处理,逻辑更简洁也不会出现异步状态更新的问题

内容的提问来源于stack exchange,提问作者LeoM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:06:05