React搜索建议组件渲染时建议列表出现多余分号项问题
React SearchBar联想列表额外渲染分号问题
问题描述
开发带联想建议功能的SearchBar组件时遇到渲染异常:遍历包含5条商品数据的productsData生成建议列表时,列表底部出现了一个来源不明的分号作为额外列表项,效果如下:
原有问题代码如下:
import React from 'react'; import { FiSearch } from 'react-icons/fi'; import '../CSS/SearchBar.css' import productsData from './../productsData.json' import 'bootstrap/dist/css/bootstrap.min.css' class SearchBar extends React.Component { constructor(props) { super(props); this.state = { typed:"" } this.userTyped = this.userTyped.bind(this); } userTyped(e) { this.setState({ typed: e.target.value }) } render() { return ( <div className='searchbar'> <div className='wrapper'> <input type='text' value={this.state.typed} onChange={this.userTyped} /> <button> <FiSearch size={18}/> </button> </div> <ul className='list-group suggestions'> {productsData.map((item) => { return ( <button id='list-item' className='list-group-item list-group-item-action'> {item.title} </button> ) })}; {/* 注意上面map闭合花括号后面多了个分号 */} </ul> </div> ) } }
问题根因
多余的分号是直接写在代码里的:productsData.map(...) 闭合大括号的外面多写了一个;。
JSX的渲染规则是:只有写在{}插值语法内部的内容会被当做JavaScript表达式解析执行,{}外面的所有普通字符都会被直接当做文本节点渲染到DOM里。这个分号在插值表达式外面,就被直接渲染到了<ul>内部,成了最后一个多余的列表项。
另外代码还有两个不规范的点,会触发警告或潜在问题:
- 用
map遍历渲染列表时,没有给每个遍历生成的顶层元素设置唯一key属性,React会抛出渲染警告 <ul>标签的合法直接子元素只能是<li>,直接把<button>作为ul的子元素不符合HTML语义规范;同时多个元素共用同一个idlist-item,违反了id全局唯一的规范。
修复方案
- 删掉
map表达式闭合大括号后面多余的分号 - 给遍历项添加唯一
key属性 - 用
<li>包裹按钮,符合ul的语义要求,移除重复id
修复后的完整代码:
import React from 'react'; import { FiSearch } from 'react-icons/fi'; import '../CSS/SearchBar.css' import productsData from './../productsData.json' import 'bootstrap/dist/css/bootstrap.min.css' class SearchBar extends React.Component { constructor(props) { super(props); this.state = { typed:"" } this.userTyped = this.userTyped.bind(this); } userTyped(e) { this.setState({ typed: e.target.value }) } render() { return ( <div className='searchbar'> <div className='wrapper'> <input type='text' value={this.state.typed} onChange={this.userTyped} /> <button> <FiSearch size={18}/> </button> </div> <ul className='list-group suggestions'> {productsData.map((item, index) => { return ( <li key={item.id || index} className="list-group-item p-0"> <button className='list-group-item-action w-100 text-start border-0 bg-transparent p-2' > {item.title} </button> </li> ) })} </ul> </div> ) } }
内容的提问来源于stack exchange,提问作者Alvino
相关产品推荐
相关产品推荐

