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

如何将每页静态数据传入跨页面共享的Hero组件?

实现跨页面共享有状态Hero组件的正确方案

结合Next.js App Router的静态预取能力与React Context,可以完美解决这个问题——既保留静态页面生成特性,又能让Hero组件跨页面保持状态不重渲染,实现无缝WebGL过渡效果。具体步骤如下:

1. 创建Hero数据上下文

定义一个Context用于存储当前页面的Hero静态数据,并提供更新方法,实现页面与Hero组件间的数据传递:

// app/hero-context.js
'use client';

import { createContext, useContext, useState } from 'react';

const HeroContext = createContext({
  heroData: null,
  updateHeroData: () => {}
});

export function HeroProvider({ children }) {
  const [heroData, setHeroData] = useState(null);

  const updateHeroData = (data) => {
    setHeroData(data);
  };

  return (
    <HeroContext.Provider value={{ heroData, updateHeroData }}>
      {children}
    </HeroContext.Provider>
  );
}

export function useHeroContext() {
  return useContext(HeroContext);
}

2. 在根布局中挂载Hero组件与Context Provider

将Hero组件放在根layout.js中,确保页面切换时组件不会被卸载;同时用HeroProvider包裹整个应用,让页面可以向Context注入数据:

// app/layout.js
import { HeroProvider } from './hero-context';
import Hero from './components/Hero';

export default function RootLayout({ children }) {
  return (
    <html lang="zh-CN">
      <body>
        <HeroProvider>
          <Hero />
          {children}
        </HeroProvider>
      </body>
    </html>
  );
}

3. 页面预取静态Hero数据并注入Context

在[slug]/page.js中,通过服务器组件预取当前页面的Hero数据,再通过一个轻量客户端组件将数据更新到Context中:

// app/[slug]/page.js
import getPage from '@/lib/cms/getPage';
import { HeroDataUpdater } from './hero-data-updater';

// 生成静态路由参数
export async function generateStaticParams() {
  const pages = await getPagesFromCMS();
  return pages.map(page => ({ slug: page.slug }));
}

// 服务器组件预取页面数据
export default async function Page({ params }) {
  const pageData = await getPage(params.slug);
  const heroData = pageData.hero;

  return (
    <>
      <HeroDataUpdater heroData={heroData} />
      <main>
        {/* 页面其他内容 */}
      </main>
    </>
  );
}

对应的客户端更新组件:

// app/[slug]/hero-data-updater.js
'use client';

import { useHeroContext, useEffect } from '../hero-context';

export function HeroDataUpdater({ heroData }) {
  const { updateHeroData } = useHeroContext();

  useEffect(() => {
    updateHeroData(heroData);
  }, [heroData, updateHeroData]);

  return null;
}

4. 改造Hero为有状态组件,消费Context数据

Hero组件作为客户端组件,从Context获取数据,用useRef保存WebGL等状态,页面切换时仅更新数据并触发过渡动画,不重渲染整个组件:

// app/components/Hero.js
'use client';

import { useHeroContext, useEffect, useRef } from '../hero-context';

export default function Hero() {
  const { heroData } = useHeroContext();
  const webglInstanceRef = useRef(null); // 保存WebGL实例或动画状态

  useEffect(() => {
    if (!heroData || !webglInstanceRef.current) return;
    // 根据新的Hero数据触发WebGL无缝过渡动画
    webglInstanceRef.current.triggerTransition(heroData);
  }, [heroData]);

  return (
    <div className="hero">
      <canvas ref={webglInstanceRef}></canvas>
      {heroData && (
        <div className="hero-content">
          {/* 根据Hero数据类型渲染对应内容 */}
          {heroData.type === 'image' && <img src={heroData.src} alt={heroData.alt} />}
          {heroData.type === 'carousel' && <Carousel items={heroData.items} />}
          {heroData.type === 'video' && <video src={heroData.src} muted loop playsInline />}
        </div>
      )}
    </div>
  );
}

方案优势

  • 保留静态生成:所有Hero数据均在服务器端预取,不影响页面静态生成特性,避免运行时调用CMS的不合理性。
  • 组件状态持久:Hero组件挂载在根布局中,页面切换时不会被卸载,WebGL等状态得以保留。
  • 数据传递高效:通过Context实现页面与Hero组件的静态数据传递,逻辑清晰且性能优异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:30:18