React组件迁移TypeScript时向数组推JSX元素报TS2345错误怎么解决?
错误原因
你声明的Element是浏览器原生DOM元素的TS类型,而<BsStarFill />是React生成的虚拟元素,对应类型为JSX.Element,二者类型不匹配,所以触发TS2345报错。此外你当前代码的useEffect依赖数组为空,只会在组件挂载时执行一次,后续stars prop变化时不会更新评分,属于隐藏逻辑bug。
解决方案
最小改动方案
仅修改类型声明和补全依赖即可解决问题:
- 将
useState和临时数组的类型从Element[]改为JSX.Element[] - 在
useEffect依赖数组中加入stars,确保props更新时重新计算星星数组
修改后代码如下:
import React, { useState, useEffect } from "react"; import { BsStarFill } from "react-icons/bs"; interface PropsInterface { stars: number; big?: boolean; } const Stars: React.FC<PropsInterface> = ({ stars, big }) => { const [array, setArray] = useState<JSX.Element[]>([]); useEffect(() => { let starsArray: JSX.Element[] = []; let starsAmount: number = Math.round(stars) / 2; for (let i = 0; i < 5; i++) { if (starsAmount > i) { starsArray.push(<BsStarFill className="star--filled" key={i} />); } else { starsArray.push(<BsStarFill className="star--unfilled" key={i} />); } } setArray(starsArray); }, [stars]); // 补全依赖 return ( <div className={big ? "stars --bigstars" : "stars"}> {array} {/* 原有Object.values.map为冗余写法,可直接渲染数组 */} </div> ); }; export default Stars;
优化写法方案
星星数组不需要存储在state中,也不需要useEffect,可以直接在渲染阶段计算生成,代码更精简,无额外状态开销:
import React from "react"; import { BsStarFill } from "react-icons/bs"; interface PropsInterface { stars: number; big?: boolean; } const Stars: React.FC<PropsInterface> = ({ stars, big }) => { const starsAmount = Math.round(stars) / 2; // 直接生成星星元素数组 const starsArray = Array.from({ length: 5 }, (_, i) => ( <BsStarFill className={i < starsAmount ? "star--filled" : "star--unfilled"} key={i} /> )); return ( <div className={big ? "stars --bigstars" : "stars"}> {starsArray} </div> ); }; export default Stars;
内容的提问来源于stack exchange,提问作者Tomas Gomez Belcastro
相关产品推荐
相关产品推荐

