NextJS生产环境ISR页面刷新状态不更新、内容闪烁如何修复?
问题根因
你遇到的闪烁本质是两个数据源不同步导致的:
getStaticProps搭配revalidate:1属于NextJS的增量静态再生(ISR)逻辑,这个配置的规则是:用户请求时先直接返回已经缓存的静态页面,后台才会静默触发重新渲染生成新页面,下一次用户访问才会返回更新后的内容,所以首次拿到的页面大概率是旧缓存数据- 客户端挂载后又触发了一次API拉取,拿到最新数据后替换了页面上的旧值,就出现了跳变闪烁
修复方案
方案1:删除客户端重复拉取逻辑(最推荐,性能最好)
直接用getStaticProps传递下来的props作为唯一数据源,不要在客户端重复调用API,从根源上消除两个数据源的差异,就不会有闪烁。
代码修改示例:
// 页面组件直接接收props里的data,删掉useEffect里的fetchNewData和loading判断逻辑 export default function Page({ data, error }) { if (error) return "Error!"; // 直接用服务端返回的data渲染,不需要额外拉取 return <div>{data.content}</div> } export async function getStaticProps() { try { const response = await fetch(`link`); const data = await response.json(); return { props: { data: data, error: null }, revalidate: 1, }; } catch (e) { return { props: { data: null, error: "请求失败" }, revalidate: 1, } } }
方案2:切换为服务端渲染(SSR),保证每次返回最新数据
如果你的业务对数据实时性要求极高,不能接受ISR的缓存延迟,直接把getStaticProps换成getServerSideProps,每次用户请求都会实时拉取最新数据返回,不会有旧缓存问题,也不需要客户端额外拉取:
代码示例:
export async function getServerSideProps() { try { const response = await fetch(`link`); const data = await response.json(); return { props: { data: data, error: null } }; } catch (e) { return { props: { data: null, error: "请求失败" } } } }
方案3:保留客户端拉取,做平滑更新无感知替换
如果你确实需要客户端主动拉取最新数据,可以去掉首次渲染的loading判断,默认先展示服务端返回的旧数据,客户端拉到新数据后静默替换,还可以加过渡动画弱化变化感知:
代码示例:
import { useState, useEffect } from 'react' export default function Page({ data: serverData }) { const [data, setData] = useState(serverData) const [error, setError] = useState(null) useEffect(() => { const fetchNewData = async () => { try { const res = await fetch('your-api-link') const newData = await res.json() // 只有数据真的变化了才更新,避免无意义重渲染 if (JSON.stringify(newData) !== JSON.stringify(serverData)) { setData(newData) } } catch (e) { setError(e.message) } } fetchNewData() }, []) if (error) return "Error!"; // 全程不展示loading,直接渲染当前数据,变化时可以加CSS过渡 return <div className="transition-all duration-300">{data.content}</div> }
内容的提问来源于stack exchange,提问作者Floky99
相关产品推荐
相关产品推荐

