如何用React组件替代HTML字符串实现带Link的字母分类导航网格?
问题
我之前通过构建HTML字符串并使用dangerouslySetInnerHTML渲染来创建导航网格,但现在需要用react-router-dom的Link组件替代<a>标签,不再使用HTML字符串。示例是<Link to={item.path}>{item.name}</Link>。
我之前的实现代码如下:
import React, { Fragment } from 'react'; import { Link } from 'react-router-dom'; const Menu = props => { const sortedList = props.list.sort((a,b) => (a.name < b.name) ? -1 : (a.name > b.name) ? 1 : 0); const mapToAlphaGrid = () => { const cap = '</div>'; const max = sortedList.length; let lastChar=""; let row = '<div class="row">'; let col = '<div class="grid-col col-4">'; let html = row; let isCap = false; for(var i=0; i < max; i++ ){ let item = sortedList[i]; let char = item.name.charAt(0); if(char > lastChar){ let alphaTitle = `<div class="alpha-title">${char}</div>` html += isCap ? cap + col + alphaTitle : col + alphaTitle; isCap = true; } html += `<a class="link" href=${item.path}>${item.name}</a>`; lastChar = char; if(i >= max-1){ return html + cap + cap; } } } return( <div dangerouslySetInnerHTML={{ __html: mapToAlphaGrid() }} /> ) } export default Menu;
我希望用React组件实现上述网格(部分列包含多个Link组件),请问该如何实现?
回答
嘿,这事儿不难!核心就是把之前拼接HTML字符串的逻辑,改成生成React元素数组的方式,彻底抛弃dangerouslySetInnerHTML——既安全,又完全符合React的组件化思路。我给你重写了代码,还优化了分组逻辑,比原来的循环更清晰:
import React from 'react'; import { Link } from 'react-router-dom'; const Menu = ({ list }) => { // 先对列表按名称排序,用扩展运算符避免修改原数组 const sortedList = [...list].sort((a, b) => a.name.localeCompare(b.name)); // 用reduce把列表按首字母分组,统一转大写避免大小写分组混乱 const groupedByLetter = sortedList.reduce((groups, item) => { const firstChar = item.name.charAt(0).toUpperCase(); if (!groups[firstChar]) { groups[firstChar] = []; } groups[firstChar].push(item); return groups; }, {}); // 渲染网格:每3个字母组为一行(对应col-4的布局) const renderGrid = () => { const letters = Object.keys(groupedByLetter); const gridRows = []; // 按每行3列拆分字母组 for (let i = 0; i < letters.length; i += 3) { const rowColumns = []; // 处理当前行的列(最多3个) for (let j = i; j < i + 3 && j < letters.length; j++) { const letter = letters[j]; const items = groupedByLetter[letter]; // 渲染单个列:包含字母标题和对应的Link组件列表 const column = ( <div key={letter} className="grid-col col-4"> <div className="alpha-title">{letter}</div> {items.map(item => ( <Link key={item.path} to={item.path} className="link"> {item.name} </Link> ))} </div> ); rowColumns.push(column); } // 把当前行加入结果数组 gridRows.push( <div key={`row-${i}`} className="row"> {rowColumns} </div> ); } return gridRows; }; return <div className="menu-grid">{renderGrid()}</div>; }; export default Menu;
代码说明:
- 分组优化:用
reduce把排序后的列表按首字母分组,比原来的循环拼接逻辑更易读、易维护,还加了首字母大写处理,避免"A"和"a"分成两组的问题。 - 组件化渲染:不再拼接字符串,而是直接生成React元素——每个列是一个
div,里面包含字母标题和多个Link组件,完全符合React的渲染规范。 - 布局适配:按照你原来的
col-4布局(每行3列),把字母组按每3个拆分成一行,和原来的HTML结构效果完全一致。 - 安全合规:彻底移除了
dangerouslySetInnerHTML,避免了XSS风险,也能正常使用React的所有特性(比如组件状态、生命周期等)。
如果你的首字母不需要统一大写,直接去掉.toUpperCase()就行啦!
内容的提问来源于stack exchange,提问作者me-me
相关产品推荐
相关产品推荐

