ReactJS如何匹配两数组id实现双重搜索并解决搜索后标签消失问题
问题根源
- 你把每个图书的genre标签存在了
<Book>子组件的内部state里,当搜索过滤时,不符合条件的<Book>组件会被直接卸载,清空搜索词后重新渲染的是全新的<Book>实例,内部state自然会重置,导致标签消失 - 你父组件其实已经维护了全量的
genres全局数组,完全可以直接复用这个数据,不需要在子组件重复存状态
具体修改方案
1. 修改子组件,删除内部标签状态,从全局genres中读取当前图书的标签
这样标签数据存在父组件,不会因为子组件被卸载丢失:
export default function Book({ book, genres, onAddGenre }) { // 直接从全局genres过滤当前图书对应的标签,无需内部state维护 const genreTags = genres.filter(genre => genre.id === book.id) function handleAddGenre(e) { const val = { id: book.id, label: e.target.value, } if (e.key === 'Enter' && val.label) { // 查重逻辑改为从全局genres判断,避免重复添加 if (genres.find(genre => genre.id === book.id && genre.label.toLowerCase() === val.label.toLowerCase())) { return } onAddGenre(val) e.target.value = "" } } return ( <> <div className="book-div"> <p>{book.title}</p> <p>Written By: {book.author}</p> </div> <div className="tag-div"> <ul> { genreTags.map(tag => { // 不要用uuid生成key,避免每次渲染都重建节点 return <li key={`${book.id}-${tag.label}`}> {tag.label} </li> })} </ul> </div> <input type="text" placeholder="Add a genre" onKeyDown={handleAddGenre} /> </> ); }
2. 修复现有代码的其他错误点
这些错误会导致功能无法正常运行,需要同步修改:
- 父组件过滤逻辑里的
searchGenres.length是笔误,改为searchGenre.length - SearchTitle组件里的
value={search}改为value={searchTitle},onSearch改为onSearchTitle - SearchGenre组件里的
onSearchTag改为onSearchGenre - 可以把父组件的三段过滤逻辑合并,更清晰不容易出错:
// 替换原来的filterGenres、filterBooks、filterBookGenres逻辑 const filteredBooks = books.filter(book => { // 匹配书名条件 const matchTitle = book.title.toLowerCase().includes(searchTitle.toLowerCase()) // 匹配genre条件,没有输入genre时直接通过 const matchGenre = searchGenre.trim() === "" ? true : genres.some(genre => genre.id === book.id && genre.label.toLowerCase().includes(searchGenre.toLowerCase())) return matchTitle && matchGenre }) // 渲染时直接遍历filteredBooks即可 const book = filteredBooks.map(book => { return ( <Book key={book.id} book={book} genres={genres} onAddGenre={handleAllGenres} /> ) })
3. 可选优化:避免组件不必要重渲染
如果希望减少过滤时的组件重渲染开销,可以用React.memo包裹<Book>组件,只要props不变就不会触发重渲染:
import { memo } from 'react' export default memo(function Book({ book, genres, onAddGenre }) { // 原有组件逻辑 })
内容的提问来源于stack exchange,提问作者may cheynack
相关产品推荐
相关产品推荐

