React JSX中已过滤数据的第二个函数无法渲染<li>元素的原因
问题:React嵌套数组过滤后无法渲染元素
我正在React JSX中开发一个简易搜索栏组件,需要渲染包含搜索关键词的元素列表。具体实现为:获取元素数组后,使用.filter()函数筛选匹配搜索关键词的元素,再通过.map()函数遍历结果并渲染<li>元素。由于两个数据集结构存在差异(其中一个为嵌套数组),我编写了两个处理函数:
第一个函数针对单层数组,可正常渲染<li>元素;第二个函数针对嵌套数组,虽能正确过滤数据并在控制台打印出结果,但无法渲染<li>元素。相关代码如下:
<ul> { this.state.searchQuery && this.props.searchDB.projects.filter((project)=> { if (this.state.searchQuery === '' || this.state.searchQuery === null) { return project; } else if (project.projectName.toLowerCase().includes(this.state.searchQuery.toLowerCase())) { return project; } else { return null } }).map((project, index) => { //THIS WORKS AS EXPECTED return( <li key={'project_' + index}> {index + '_' + project.projectName} </li> ) }) } { this.state.searchQuery && this.props.searchDB.mentions.forEach((mentionYear) => { mentionYear.filter((mention) => { if (this.state.searchQuery === '' || this.state.searchQuery === null) { return mention } else if (mention.mentionTitle.toLowerCase().includes(this.state.searchQuery.toLowerCase())) { return mention } else { return null } }).map((mention, mentionIndex) => { console.log(mention.mentionTitle) //THIS LOGS DATA AS IT SHOULD BUT DOESN'T RENDER ELEMENTS return( <li key={'project_' + mentionIndex}> {mentionIndex + '_' + mention.mentionTitle} </li> ) }) }) } </ul>
请问是什么原因导致第二个函数无法渲染
原因与解决方案
核心问题是你用了forEach遍历嵌套数组,而forEach本身没有返回值(返回undefined),React无法从undefined中渲染任何元素。而第一个函数里用的是链式调用的filter().map(),会返回一个包含<li>元素的数组,React可以正常渲染这个数组。
要解决这个问题,需要把forEach换成map,因为map会返回一个新数组,里面包含每一层处理后得到的<li>元素集合。另外还要注意:
filter里的返回值应该是布尔值,而不是直接返回元素或null,这样filter才能正确筛选元素- 嵌套数组处理后可能会产生空数组,需要扁平化或者过滤掉空数组,避免渲染空内容
修正后的代码如下:
<ul> {/* 原单层数组处理逻辑(优化filter判断) */} { this.state.searchQuery && this.props.searchDB.projects.filter(project => { if (!this.state.searchQuery) return true; return project.projectName.toLowerCase().includes(this.state.searchQuery.toLowerCase()); }).map((project, index) => ( <li key={'project_' + index}> {index + '_' + project.projectName} </li> )) } {/* 修正后的嵌套数组处理逻辑 */} { this.state.searchQuery && this.props.searchDB.mentions .map(mentionYear => { return mentionYear.filter(mention => { if (!this.state.searchQuery) return true; return mention.mentionTitle.toLowerCase().includes(this.state.searchQuery.toLowerCase()); }).map((mention, mentionIndex) => ( <li key={'mention_' + mentionIndex + '_' + mention.mentionTitle}> {mentionIndex + '_' + mention.mentionTitle} </li> )); }) // 扁平化数组,避免嵌套数组导致的渲染异常 .flat() } </ul>
说明:
- 把
forEach替换为map,让每一层处理都返回对应的元素数组 - 优化了
filter的判断逻辑,直接返回布尔值,符合filter的API规范 - 使用
flat()扁平化嵌套数组,确保最终传给React的是一维元素数组 - 调整了key值,避免和第一个数组的key重复,保证key的唯一性
内容的提问来源于stack exchange,提问作者Jiří Honzák
相关产品推荐
相关产品推荐

