React.js如何将API返回的FAQ数组数据渲染到Material UI Accordion组件
实现方案
1. 接口数据请求与状态管理
首先在组件内通过状态存储接口返回的FAQ数据,同时补充加载、错误状态处理避免页面异常:
- 用
useState定义faqList存储问答数组、loading控制加载状态、error存储错误信息 - 用
useEffect在组件挂载时发起API请求,拿到数据后存入faqList状态
2. 动态渲染Accordion组件
将原有的静态Accordion代码修改为数组遍历渲染形式,直接替换占位文本为接口返回的对应字段:
- 遍历
faqList数组,每个元素对应渲染一个Accordion组件,绑定唯一key值 - AccordionSummary区域替换为
item.question,AccordionDetails区域替换为item.answer - 如有分组需求,可先按
section字段对数据做分组处理,再按分组层级渲染
完整代码示例
import { useState, useEffect } from 'react'; import Accordion from '@mui/material/Accordion'; import AccordionSummary from '@mui/material/AccordionSummary'; import AccordionDetails from '@mui/material/AccordionDetails'; import Typography from '@mui/material/Typography'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; const FAQPage = () => { const [faqList, setFaqList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); // 组件挂载时请求FAQ接口数据 useEffect(() => { const fetchFAQ = async () => { try { const response = await fetch('替换为你的实际FAQ接口地址'); if (!response.ok) throw new Error('接口请求失败'); const result = await response.json(); setFaqList(result); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchFAQ(); }, []); // 加载态展示 if (loading) return <Typography sx={{ p: 3 }}>加载中...</Typography>; // 错误态展示 if (error) return <Typography sx={{ p: 3, color: 'error.main' }}>{error}</Typography>; // 按section分组(需要分组时开启) /* const groupedFaq = faqList.reduce((acc, item) => { if (!acc[item.section]) acc[item.section] = []; acc[item.section].push(item); return acc; }, {}); */ return ( <div style={{ maxWidth: 800, margin: '2rem auto', padding: '0 1rem' }}> {/* 无需分组直接遍历数组 */} {faqList.map((item, index) => ( <Accordion key={index}> <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls={`faq-content-${index}`} id={`faq-header-${index}`} > <Typography fontWeight={500}>{item.question}</Typography> </AccordionSummary> <AccordionDetails> <Typography>{item.answer}</Typography> {/* 如需展示适用范围可开启下面代码 */} {/* <Typography variant="caption" color="text.secondary" sx={{ mt: 1, display: 'block' }}> 适用应用:{item.application} </Typography> */} </AccordionDetails> </Accordion> ))} {/* 分组模式渲染示例 {Object.entries(groupedFaq).map(([section, items]) => ( <div key={section} sx={{ mb: 3 }}> <Typography variant="h6" sx={{ mb: 1 }}>{section}</Typography> {items.map((item, index) => ( <Accordion key={`${section}-${index}`}> <AccordionSummary expandIcon={<ExpandMoreIcon />}> <Typography fontWeight={500}>{item.question}</Typography> </AccordionSummary> <AccordionDetails> <Typography>{item.answer}</Typography> </AccordionDetails> </Accordion> ))} </div> ))} */} </div> ); }; export default FAQPage;
内容的提问来源于stack exchange,提问作者Daniel Döbereiner
相关产品推荐
相关产品推荐

