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

如何从远程GraphQL获取数据作为全局值在应用中使用?

解决Next.js全局获取CMS GraphQL数据的方案

你想要在所有页面无需重复写获取代码就能访问远程CMS的GraphQL数据,之前用global对象的方法因为异步问题走不通,下面给你几个靠谱的实现方式:

一、React Context全局管理(通用所有Next.js版本)

这个方法适合数据可能动态更新,且需要在客户端、服务器端都能访问的场景,页面里完全不用写数据获取代码:

  1. 创建全局数据Context
    新建contexts/GlobalDataContext.js文件:
import { createContext, useContext } from 'react';

const GlobalDataContext = createContext(null);

export function GlobalDataProvider({ children, data }) {
  return (
    <GlobalDataContext.Provider value={data}>
      {children}
    </GlobalDataContext.Provider>
  );
}

export function useGlobalData() {
  return useContext(GlobalDataContext);
}
  1. 在_app.js中统一获取数据并注入Context
    如果是Pages Router的_app.js,用getInitialProps在页面初始化前完成数据获取:
import { GlobalDataProvider } from '../contexts/GlobalDataContext';
import request from 'graphql-request';
import { gql } from 'graphql-request';

MyApp.getInitialProps = async () => {
  const mydata = await request(
    'https://example.com/graphql',
    gql`
      query Data {
        mydata
      }
    `
  );
  return { globalData: mydata };
};

function MyApp({ Component, pageProps, globalData }) {
  return (
    <GlobalDataProvider data={globalData}>
      <Component {...pageProps} />
    </GlobalDataProvider>
  );
}

export default MyApp;
  1. 任意页面直接使用数据
import { useGlobalData } from '../contexts/GlobalDataContext';

function SomePage() {
  const globalData = useGlobalData();
  return <div>{globalData.mydata}</div>;
}

export default SomePage;

二、构建时预取静态数据(适合不常更新的内容)

如果你的CMS数据很少变动,可以在构建阶段就把数据拉取下来,通过环境变量全局访问:

  1. 在next.config.js中获取数据并注入环境变量
const { request, gql } = require('graphql-request');

module.exports = async () => {
  // 构建阶段异步获取CMS数据
  const mydata = await request(
    'https://example.com/graphql',
    gql`
      query Data {
        mydata
      }
    `
  );

  return {
    env: {
      // 加NEXT_PUBLIC_前缀让客户端能访问
      NEXT_PUBLIC_GLOBAL_DATA: JSON.stringify(mydata),
    },
    // 其他Next.js配置项
  };
};
  1. 页面中直接读取环境变量
const globalData = JSON.parse(process.env.NEXT_PUBLIC_GLOBAL_DATA);

function SomePage() {
  return <div>{globalData.mydata}</div>;
}

export default SomePage;

注意:这种方式的数据是构建时固化的,CMS数据更新后需要重新构建部署才能生效。

三、Next.js 13+ App Router 用Server Component布局

如果用App Router,直接在根布局里以Server Component的身份获取数据,天然支持异步,不用额外处理:

  1. 在app/layout.js中获取数据
import { request, gql } from 'graphql-request';
import { GlobalDataProvider } from './contexts/GlobalDataContext';

export default async function RootLayout({ children }) {
  // Server Component中直接异步获取数据
  const globalData = await request(
    'https://example.com/graphql',
    gql`
      query Data {
        mydata
      }
    `
  );

  return (
    <html lang="zh-CN">
      <body>
        <GlobalDataProvider data={globalData}>
          {children}
        </GlobalDataProvider>
      </body>
    </html>
  );
}

之后页面同样通过useGlobalData Hook获取数据即可,完全不用写获取逻辑。

为什么之前的global方法行不通?

  • 服务器端的global和客户端的window是完全独立的上下文,客户端根本访问不到服务器端赋值的global.my_data。
  • 异步获取数据时,页面渲染流程不会等待异步操作完成,要么global.my_data是未解析的Promise(没加await),要么页面已经渲染完成了数据还没赋值(加了await但时机不对)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:25:01