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

如何在Remix中实现Strapi组件动态渲染及Teaser全局取最新博客

解决方案

要实现Teaser组件在任意页面的Strapi动态sections中都能SSR获取最新3篇博客,按以下步骤操作:

1. 编写获取最新博客的公用函数

创建独立函数用于从Strapi拉取排序后的3篇最新博客,方便多页面复用:

export async function getLatestBlogs() {
  const token = process.env.STRAPI_API_TOKEN;
  if (!token) throw new Error("Strapi API Token environment variable is not set.");

  const path = `/blogs`;
  const options = { headers: { Authorization: `Bearer ${token}` } };

  const urlParamsObject = {
    sort: ["publishedAt:desc"], // 按发布时间倒序
    pagination: { limit: 3 }, // 只取3篇
    populate: {
      thumbnail: { fields: ["url"] }, // 按需获取缩略图字段
      seo: { fields: ["title", "description"] } // 可根据实际需求调整
    },
  };

  const baseUrl = getStrapiURL();
  const blogs = await fetchAPI(path, urlParamsObject, options);

  return blogs.data;
}

2. 修改页面Loader,并行获取页面与博客数据

在所有可能包含Teaser的页面(首页、关于页等)的Loader中,用Promise.all并行拉取数据,保证SSR且不影响性能:

// 以首页Loader为例
export async function loader({ params }) {
  // 并行执行两个请求,避免串行等待
  const [pageData, latestBlogs] = await Promise.all([
    getPageBySlug(params.slug),
    getLatestBlogs(),
  ]);

  return {
    ...pageData,
    latestBlogs, // 将博客数据加入返回结果
  };
}

如果多个页面需要此逻辑,可用高阶函数封装减少重复代码:

// 公用Loader封装函数
export async function withLatestBlogs(loaderFn) {
  return async (args) => {
    const [pageData, latestBlogs] = await Promise.all([
      loaderFn(args),
      getLatestBlogs(),
    ]);
    return { ...pageData, latestBlogs };
  };
}

// 首页Loader使用封装
export const loader = withLatestBlogs(async ({ params }) => {
  return getPageBySlug(params.slug);
});

3. 传递博客数据到Teaser组件

修改页面组件和sectionRenderer,将博客数据传递给Teaser:

修改首页组件

export default function Home() {
  const { page, latestBlogs } = useLoaderData();
  const { attributes } = page || {};

  if (attributes) {
    const { sections } = attributes;
    return (
      <main>
        {/* 将latestBlogs传给sectionRenderer */}
        {sections.map((section, index) => 
          sectionRenderer(section, index, latestBlogs)
        )}
      </main>
    );
  } else {
    return <Error />;
  }
}

修改sectionRenderer函数

import Hero from "../components/Hero";
import Teaser from "../components/Teaser";

export function sectionRenderer(section, index, latestBlogs) {
  switch (section.__component) {
    case "sections.hero":
      return <Hero key={index} data={section} />;
    case "sections.teaser":
      // 将博客数据传给Teaser组件
      return <Teaser key={index} data={section} blogs={latestBlogs} />;
    default:
      return null;
  }
}

4. 实现Teaser组件渲染逻辑

在Teaser组件中使用传入的博客数据渲染内容:

import getStrapiURL from "../utils/getStrapiURL"; // 复用你的Strapi URL工具函数

export default function Teaser({ data, blogs }) {
  // data是Strapi中Teaser区块的配置(如标题、副标题等)
  const { title, subtitle } = data.attributes;

  return (
    <section className="teaser-container">
      <h2>{title}</h2>
      {subtitle && <p className="teaser-subtitle">{subtitle}</p>}
      
      <div className="teaser-blog-grid">
        {blogs.map((blog) => {
          const { id, attributes } = blog;
          return (
            <article key={id} className="teaser-blog-card">
              {attributes.thumbnail && (
                <img 
                  src={`${getStrapiURL()}${attributes.thumbnail.url}`} 
                  alt={attributes.title}
                  className="teaser-blog-image"
                />
              )}
              <h3 className="teaser-blog-title">{attributes.title}</h3>
              <p className="teaser-blog-excerpt">{attributes.excerpt}</p>
              <a href={`/blog/${attributes.slug}`} className="teaser-read-more">
                阅读更多
              </a>
            </article>
          );
        })}
      </div>
    </section>
  );
}

注意事项

  • 单篇博客详情页等不需要Teaser的页面,无需在Loader中调用getLatestBlogs,避免不必要的API请求。
  • 可根据Strapi中Blog模型的实际字段调整getLatestBlogs中的populate配置,只获取需要的字段减少数据传输。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:57:07