React嵌套.map()无元素返回?NFT图片网格渲染异常
React嵌套Map渲染无内容的问题排查与修复
核心问题梳理与修复步骤
1. 内层Map语法错误
你的内层map箭头函数写法存在语法问题:箭头函数如果用大括号包裹代码块,需要显式return,但你当前的写法不符合规范,导致没有返回JSX元素。
- 错误写法:
ele.map((item, innerIdx) => ( return( <img src={item}></img> ) ))
- 正确写法(二选一):
// 隐式返回,省略大括号与return ele.map((item, innerIdx) => <img key={innerIdx} src={item} />) // 显式返回,保留大括号 ele.map((item, innerIdx) => { return <img key={innerIdx} src={item} /> })
注意:必须给img添加唯一key,避免React渲染警告。
2. nftArr的初始化与状态管理问题
你在组件顶层声明的let nftArr属于普通变量,每次组件渲染都会被重置;且初始化时NFTPayload是空数组,导致rowCount = Math.round(-1 / props.columnCount)得到NaN,内层数组长度异常。
建议将nftArr改为状态变量,确保数据更新时组件能同步渲染:
const [nftArr, setNftArr] = useState([]);
3. useEffect依赖与逻辑错误
- 依赖缺失:第二个
useEffect的依赖数组缺少props.columnCount,导致列数变化时不会重新计算布局; - 数据赋值逻辑错误:
outerCounter在每列循环时都重置为0,导致所有列都填充相同的前rowCount个元素; - 直接修改状态:
NFTPayload.reverse()直接修改了state数组,会导致状态污染,应该创建数组副本再操作。
修复后的useEffect逻辑:
useEffect(() => { if (!NFTPayload.length) return; // 创建数组副本再反转,避免污染原状态 const reversedNFT = [...NFTPayload].reverse(); // 用ceil计算行数,确保所有元素都能被分配 const calculatedRowCount = Math.ceil(reversedNFT.length / props.columnCount); const newNftArr = Array(props.columnCount).fill().map(() => []); let counter = 0; // 按行填充列,确保元素均匀分配 for (let j = 0; j < calculatedRowCount; j++) { for (let i = 0; i < props.columnCount; i++) { if (counter < reversedNFT.length) { newNftArr[i].push(reversedNFT[counter]); counter++; } } } setNftArr(newNftArr); }, [NFTPayload, props.columnCount]);
4. 初始行数计算异常
初始时NFTPayload是空数组,itemCount = NFTPayload.length -1得到-1,导致rowCount异常。需要在有数据时再计算行数:
// 替换原rowCount的计算逻辑 const calculatedRowCount = NFTPayload.length ? Math.ceil(NFTPayload.length / props.columnCount) : 0;
修复后的完整代码
const NFTGallery = (props) => { const [NFTPayload, setNFTPayload] = useState([]); const [nftArr, setNftArr] = useState([]); useEffect(() => { setNFTPayload(smartContractArrayOfNFTs); }, []); useEffect(() => { if (!NFTPayload.length) return; const reversedNFT = [...NFTPayload].reverse(); const calculatedRowCount = Math.ceil(reversedNFT.length / props.columnCount); const newNftArr = Array(props.columnCount).fill().map(() => []); let counter = 0; for (let j = 0; j < calculatedRowCount; j++) { for (let i = 0; i < props.columnCount; i++) { if (counter < reversedNFT.length) { newNftArr[i].push(reversedNFT[counter]); counter++; } } } setNftArr(newNftArr); }, [NFTPayload, props.columnCount]); return ( <> <section className={styling.testContainer}> {nftArr.map((ele, outerIdx) => ( <div key={outerIdx} className={styling.testColumn}> {ele.map((item, innerIdx) => ( <img key={innerIdx} src={item} alt={`NFT ${outerIdx}-${innerIdx}`} /> ))} </div> ))} </section> </> ); }; export default NFTGallery;
内容的提问来源于stack exchange,提问作者Alex Bent
相关产品推荐
相关产品推荐

