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

Next/React应用如何实现数据仅加载一次,仅页面真实重载时重新请求?

Next.js 全局单次加载API数据的实现方案

你遇到的重复请求问题,通常是因为将请求逻辑放在了_app.js的getInitialProps/getServerSideProps这类每次路由切换都会触发的生命周期中,或是客户端请求没有加缓存判断导致的。

方案1:客户端状态缓存(全版本通用,最推荐)

用全局状态管理存储请求到的数据,仅当数据不存在时发起请求,页面刷新后状态自动重置,完全符合需求。你可以用轻量状态库Zustand实现,也可以用React Context、Redux等替代:

  • 第一步:创建全局存储
// stores/globalData.js
import { create } from 'zustand'

const useGlobalDataStore = create((set) => ({
  globalData: null,
  fetchGlobalData: async () => {
    const res = await fetch('你的API地址')
    const data = await res.json()
    set({ globalData: data })
  }
}))

export default useGlobalDataStore
  • 第二步:在_app.js(Pages Router)或根layout(App Router)中添加请求逻辑
// pages/_app.js(Pages Router示例)
import { useEffect } from 'react'
import useGlobalDataStore from '../stores/globalDataStore'

export default function MyApp({ Component, pageProps }) {
  const { globalData, fetchGlobalData } = useGlobalDataStore()

  // 仅当全局数据不存在时才发起请求
  useEffect(() => {
    if (!globalData) fetchGlobalData()
  }, [globalData, fetchGlobalData])

  return <Component {...pageProps} />
}

后续任意组件都可以通过这个store直接读取全局数据,不会重复发起请求。

方案2:静态变量缓存(服务端请求场景适用)

如果你需要在服务端获取数据,避免_app.js的getInitialProps重复请求,可以用静态变量缓存结果:

// pages/_app.js
import App from 'next/app'

// 定义静态缓存变量
let cachedGlobalData = null

MyApp.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext)

  // 仅缓存为空时发起请求
  if (!cachedGlobalData) {
    const res = await fetch('你的API地址')
    cachedGlobalData = await res.json()
  }

  return { ...appProps, globalData: cachedGlobalData }
}

function MyApp({ Component, pageProps, globalData }) {
  // 可以把globalData通过Context传递给子组件使用
  return <Component {...pageProps} />
}

export default MyApp

注意:该方案的缓存是服务端进程级别的,多实例部署时每个实例会独立请求一次数据,无其他副作用。

方案3:轻量场景直接使用window对象挂载

如果不想引入状态管理,也可以直接把数据挂载到全局window对象上,页面刷新时window会自动重置:

// pages/_app.js
import { useEffect, useState } from 'react'

export default function MyApp({ Component, pageProps }) {
  const [globalData, setGlobalData] = useState(null)

  useEffect(() => {
    if (!window.__GLOBAL_APP_DATA__) {
      fetch('你的API地址')
        .then(res => res.json())
        .then(data => {
          window.__GLOBAL_APP_DATA__ = data
          setGlobalData(data)
        })
    } else {
      setGlobalData(window.__GLOBAL_APP_DATA__)
    }
  }, [])

  return <Component {...pageProps} globalData={globalData} />
}

小提示:如果使用Next.js 13+的App Router,直接在根服务端Layout中发起的fetch请求默认会被全局缓存,全应用复用,也能实现减少重复请求的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:36:03