React函数组件切换mode时先渲染旧数据问题求助
解决React组件切换模式时显示旧数据的问题
嘿,我明白你遇到的困扰了——切换mode的时候,组件先蹦出旧数据,然后才加载新数据,这体验确实不太好。问题根源在于React状态更新的时机:当你调用setMode时,组件会立刻重新渲染,但你的自定义useFeedbackDistribution钩子要等到这次渲染完成后才会触发新的请求,所以这时候data还是旧的,就导致了短暂的旧数据显示。
下面给你两个简单有效的解决方案,任选其一就行:
方案1:修改自定义Hook,切换时立即清空旧数据
直接在你的feedbackDistributionReducer里调整FETCH_INIT动作,不仅开启加载状态,还把data重置为空数组。这样一来,就算组件在请求开始前先渲染了,也只会显示空内容(不会是旧数据),紧接着加载状态生效,就会显示Loading了。
修改后的reducer代码:
const feedbackDistributionReducer = (state, action) => { switch (action.type) { case "FETCH_INIT": // 重置data为空,彻底避免旧数据显示 return { ...state, isLoading: true, isError: false, data: [] }; case "FETCH_SUCCESS": return { ...state, isLoading: false, isError: false, data: action.payload }; case "FETCH_ERROR": // 错误时也清空数据,保持状态一致 return { ...state, isLoading: false, isError: true, data: [] }; default: throw new Error("Could not fetch feedback distribution"); } };
方案2:在组件里加个「切换中」的临时状态
如果不想改动Hook的核心逻辑,可以在组件内部加一个本地状态,专门标记模式切换的瞬间,强制显示Loading直到新数据加载完成。
修改后的组件代码(关键部分):
const FeedbackDistributionCard = user => { const [mode, setMode] = useState({ value: DISTRIBUTION_MODE.WEEK, label: DISTRIBUTION_MODE.WEEK }); // 新增状态:标记是否正在切换模式 const [isSwitching, setIsSwitching] = useState(false); const [{ isLoading, isError, data }] = useFeedbackDistribution(mode.value, []); // 当加载完成时,取消切换标记 useEffect(() => { if (!isLoading) { setIsSwitching(false); } }, [isLoading]); // ...你的load函数保持不变 return ( <div className="w-full h-64 sm:w-full md:w-full lg:w-3/4 xl:w-3/4 mb-4 bg-white rounded-lg shadow"> <div className="w-full h-full "> {isError && <ErrorSolid />} {/* 切换中或加载中,都显示Loading */} {(isLoading || isSwitching) ? ( <Loading /> ) : ( <div className="h-full w-full flex-col shadow p-6"> <div> <p className="font-bold float-left inline-block"> Feedback by {mode.value} </p> <Select className="w-40 z-50 float-right" options={options} onChange={e => { // 切换瞬间立刻标记为加载中 setIsSwitching(true); setMode({ label: e.label, value: e.value }); }} value={mode} /> </div> <div className="h-full w-full"> <FeedbackDistributionLineChart properties={load(data)} /> </div> </div> )} </div> </div> ); };
小提醒:修复Hook里的错误处理
顺便提一句,你的Hook里catch块有个小bug——payload: error应该是payload: err,不然会报未定义变量的错误:
catch (err) { if (!didCancel) { dispatch({ type: "FETCH_ERROR", payload: err }); // 把error改成err } }
这两个方案都能解决你的问题,选哪个看你习惯。修改后切换模式时,要么直接显示Loading,要么显示空图表,绝对不会再看到旧数据啦~
内容的提问来源于stack exchange,提问作者dragosiv
相关产品推荐
相关产品推荐

