React+TSX中TSX元素比较失败求助:原因及解决方法
问题原因与解决方法
1. JSX元素全等比较失败的原因
- React中JSX元素是
React.createElement()的语法糖,每次书写<div>...</div>都会生成新的对象引用。哪怕内容完全一致,两个JSX元素的内存地址不同,用===做全等比较时会直接判定为不相等。 - 你用
Array.fill()初始化的数组里,所有元素都是同一个JSX对象的引用,但在placeTile函数里你创建了一个新的、内容相同的JSX元素来做比较,两者引用不同,所以比较永远失败。
2. tiles[index].id返回undefined的原因
tiles数组存储的是虚拟DOM对象(React元素),而非真实DOM节点。虚拟DOM的属性都封装在props字段中,直接访问.id无法获取到值,正确写法是tiles[index].props.id。但这种方式并非最优解,下文会说明原因。
正确解决思路:用数据模型替代存JSX元素在state中
React的最佳实践是state存储数据,渲染阶段根据数据生成JSX,而非直接将JSX存入state。这种方式既便于状态比较,也能规避虚拟DOM引用带来的问题。
修改步骤:
- 定义tile的数据结构:
type Tile = { type: 'filler' | 'filled'; id: string; value: string; }; - 初始化state为数据数组:
const initialTiles: Tile[] = Array(9).fill({ type: 'filler', id: '.', value: '.' }); const [tiles, setTiles] = useState<Tile[]>(initialTiles); - 渲染时根据数据生成JSX:
return ( <div className="tile-container"> {tiles.map((tile, index) => ( <div key={index} className={tile.type} id={tile.id} onClick={() => placeTile(index)} > {tile.value} </div> ))} </div> ); - 修改
placeTile函数,直接比较数据:function placeTile(index: number) { if (tiles[index].id === '.') { const updateTile = [...tiles]; updateTile[index] = { type: 'filled', id: move, value: move }; console.log("Filled a spot"); setTiles(updateTile); } else { console.log("This is filled spot " + index); } }
其他可选比较方式(非推荐)
若因特殊需求必须存储JSX在state中,可通过比较虚拟DOM的props属性来判断:
if (tiles[index].props.id === '.' && tiles[index].props.className === 'filler') { // 执行填充逻辑 }
这种方式不推荐,因为虚拟DOM结构可能随需求变更,维护成本远高于直接存储数据模型。
内容的提问来源于stack exchange,提问作者Anirudh Agrawal
相关产品推荐
相关产品推荐

