React:如何通过Fetch API正确渲染react-icons图标?
问题描述
将社交链接数据存储在Firebase中,希望生成<li>格式的社交链接列表,但获取到的icon字段内容为<BsBehance />这类字符串,无法渲染为图标,而是直接显示该文本。目前通过Fetch API获取数据正常,编写了React代码尝试处理却未成功,需要解决图标渲染问题。
Firebase数据截图:
当前显示效果截图:
原代码:
import { useEffect, useState } from "react"; import * as ReactIcons from "react-icons/fa"; import MainWrapper from "./MainWrapper"; import classes from "./pages.module.css"; export default function Footer() { const [socialLinks, setSocialLinks] = useState([]); useEffect(() => { const fetchSocilLinks = async () => { const res = await fetch( "https://mohitdevelops-d64e5-default-rtdb.asia-southeast1.firebasedatabase.app/accounts.json" ); const data = await res.json(); let loadedData = []; for (const keys in data) { loadedData.push({ url: data[keys].url, icon: data[keys].icon, id: data[keys].id, }); } setSocialLinks(loadedData); }; fetchSocilLinks().catch((err) => { console.log(err.message); }); }, [socialLinks]); console.log(socialLinks); return ( <footer className={classes.footer__wrap}> <MainWrapper> <p>Connect with me:</p> <ul className={classes.social_links}> {socialLinks?.map(({ icon, id, url }) => { const iconLink = icon.split(/<|\/>/).filter((e) => e)[0]; const IconsComponent = ReactIcons[iconLink]; return ( <li key={id}> <a href={url} target="_blank"> <IconsComponent /> </a> </li> ); })} </ul> </MainWrapper> </footer> ); }
解决方案
核心问题分析
- 图标库导入错误:Firebase中存储的是
Bs开头的图标组件(属于Bootstrap Icons),但原代码导入的是react-icons/fa(Font Awesome图标库),导致找不到对应的组件。 - useEffect依赖错误:将
socialLinks作为useEffect的依赖,会触发无限循环请求。 - 缺少组件校验:未判断图标组件是否存在,若数据中图标名称有误会引发渲染错误。
修改后的代码
import { useEffect, useState } from "react"; // 导入Bootstrap Icons库,匹配Firebase中Bs前缀的图标 import * as ReactIcons from "react-icons/bs"; import MainWrapper from "./MainWrapper"; import classes from "./pages.module.css"; export default function Footer() { const [socialLinks, setSocialLinks] = useState([]); useEffect(() => { const fetchSocilLinks = async () => { try { const res = await fetch( "https://mohitdevelops-d64e5-default-rtdb.asia-southeast1.firebasedatabase.app/accounts.json" ); const data = await res.json(); let loadedData = []; for (const key in data) { loadedData.push({ url: data[key].url, icon: data[key].icon, id: data[key].id, }); } setSocialLinks(loadedData); } catch (err) { console.log(err.message); } }; fetchSocilLinks(); }, []); // 空依赖数组,仅组件挂载时请求一次数据 return ( <footer className={classes.footer__wrap}> <MainWrapper> <p>Connect with me:</p> <ul className={classes.social_links}> {socialLinks.map(({ icon, id, url }) => { // 提取图标组件名称,从<BsBehance />中得到BsBehance const iconName = icon.split(/<|\/>/).filter(Boolean)[0]; // 获取对应的图标组件 const IconComponent = ReactIcons[iconName]; // 组件不存在则跳过渲染 if (!IconComponent) return null; return ( <li key={id}> <a href={url} target="_blank" rel="noopener noreferrer"> <IconComponent /> </a> </li> ); })} </ul> </MainWrapper> </footer> ); }
关键修改说明
- 替换图标库:将
react-icons/fa改为react-icons/bs,匹配Firebase中的Bs前缀图标组件。 - 修复无限循环:useEffect依赖改为空数组,确保仅在组件挂载时执行一次数据请求。
- 增加组件校验:判断
IconComponent是否存在,避免因图标名称错误导致的渲染异常。 - 添加安全属性:给
<a>标签加上rel="noopener noreferrer",符合外链安全规范。
内容的提问来源于stack exchange,提问作者Mohit
相关产品推荐
相关产品推荐

