Next.js中如何调用ACF Flexible Content字段并渲染
Next.js中渲染ACF Flexible Content字段的解决方案
问题背景
在Next.js项目中,已正常获取文章标题、内容、作者、日期等字段,但无法渲染ACF的flexibleContent字段,需解决:
- 如何在组件中正确访问ACF字段数据
- 如何在
[slug].tsx页面中调用并渲染flexibleContent对象
响应数据示例
"flexibleContent": { "acfContentModules": [ { "fieldGroupName": "Post_Flexiblecontent_AcfContentModules_RawHtmlModuleGroup", "rawHtmlModule": { "fieldGroupName": "raw_html_module", "rawCss": null, "rawHtml": "Lorem Ipsum Raw html", "rawJavascript": null } } ] }
当前已实现的getStaticProps(验证正确)
你的getStaticProps代码已经正确获取了flexibleContent数据,无需修改:
export async function getStaticProps(context) { const res = await fetch('http://localhost/wp/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: ` query SinglePost($id: ID!, $idType: PostIdType!) { post(id: $id, idType: $idType) { title slug content featuredImage { node { sourceUrl altText } } date author { node { name } } flexibleContent { acfContentModules { ... on Post_Flexiblecontent_AcfContentModules_RawHtmlModuleGroup { fieldGroupName rawHtmlModule { fieldGroupName rawCss rawHtml rawJavascript } } } } } } `, variables: { id: context.params.slug, idType: 'SLUG' } }) }) const json = await res.json() return { props: { post: json.data.post, }, } }
解决方案
1. 正确访问ACF字段数据的核心要点
acfContentModules是一个数组,而非对象,不能直接通过模块名称作为属性访问。每个数组元素包含fieldGroupName标识模块类型,以及对应的模块数据(如rawHtmlModule)。
2. 在[slug].tsx中调用并渲染flexibleContent对象
修改页面组件代码,遍历acfContentModules数组,根据模块类型渲染对应内容:
import Image from 'next/image' import HeaderComponent from "../../components/common/Header/header"; import FooterComponent from "../../components/common/Footer/footer"; export default function Post(data) { const post = data.post; console.log(post); // 处理flexible content模块的渲染 const renderFlexibleContent = () => { if (!post.flexibleContent?.acfContentModules) return null; return post.flexibleContent.acfContentModules.map((module, index) => { // 根据fieldGroupName判断模块类型 switch(module.fieldGroupName) { case 'Post_Flexiblecontent_AcfContentModules_RawHtmlModuleGroup': return ( <div key={index} className="raw-html-module"> {/* 渲染原始HTML内容 */} <div dangerouslySetInnerHTML={{ __html: module.rawHtmlModule.rawHtml }} /> {/* 如果有CSS或JS,也可以在这里处理 */} {module.rawHtmlModule.rawCss && ( <style dangerouslySetInnerHTML={{ __html: module.rawHtmlModule.rawCss }} /> )} </div> ); // 可以添加更多模块类型的处理逻辑 // case 'Other_Module_Type': // return <OtherModule key={index} data={module.otherModule} />; default: return null; } }); }; return ( <div> <HeaderComponent></HeaderComponent> <header className="w3-display-container w3-content w3-wide" style={{'maxWidth':'1600px','minWidth':'500px'}} id="home"> {/* <Image className="w3-image" src="" alt="" width={1600} height={800}/> */} </header> <div className="w3-content" style={{'maxWidth':'1100px','marginBottom':'70px'}}> <h1>{post.title}</h1> <Image width="640" height="426" alt="" src={post.featuredImage.node.sourceUrl} /> <article dangerouslySetInnerHTML={{__html: post.content}}></article> </div> <div className="w3-display-container w3-content"> <p><b>Author: {post.author.node.name}</b></p> <p><b>Date: {post.date}</b></p> {/* 渲染Flexible Content */} <div className="flexible-content"> <h3>Flexible Content Modules</h3> {renderFlexibleContent()} </div> </div> <FooterComponent></FooterComponent> </div> ) }
关键说明
- 使用
map遍历acfContentModules数组,通过key={index}确保React列表渲染的稳定性 - 通过
switch-case判断fieldGroupName,针对不同模块类型编写渲染逻辑 - 对于原始HTML内容,使用
dangerouslySetInnerHTML进行渲染(注意XSS风险,确保内容安全) - 若有多个ACF模块类型,只需添加对应的
case分支即可扩展
内容的提问来源于stack exchange,提问作者Naveenbos
相关产品推荐
相关产品推荐

