ReactJS - 如何比较/过滤两个数组的匹配 id 并在双重搜索功能中使用结果?

梅切纳克

我想在我的应用程序中具有双重搜索功能。一次搜索,按书名过滤书籍。而另一个,按流派过滤书籍。两个搜索过滤器应该一起工作(如果提供了搜索词,它应该按标题和流派过滤掉)。

但是,我在应用流派搜索过滤器时遇到了困难。

** 注意**:创建时,每个流派标签的分配方式与id其所标记的书籍相同通过这种方式,我可以提取与正在搜索的类型相关的所有书籍。

对象:

book = { id: "id", title: "title", author: "author"}
genre = { id: "id", label: "label" }

父组件

export default function Books() {
  const [books, setBooks] = useState([])
  const [searchTitle, setSearchTitle] = useState("")
  const [genres, setGenres] = useState([]) 
  const [searchGenre, setSearchGenre] = useState("")

  useEffect(() => {
    fetch(`https://www.someapi.com/books`)
    .then(r => r.json())
    .then(setBooks)
  }, [])

  function handleAllGenres(val){
    setGenres([...genres, val])
  }

  const filterGenres = genres.filter(genre => {
    return genre.label.toLowerCase().includes(searchGenre.toLowerCase())
  })

  const filterBooks = books.filter(book => {
    return book.title.toLowerCase().includes(searchTitle.toLowerCase())
  })

  const filterBookGenres = filterBooks.filter(book => {    
    if (searchGenres.length > 0) {                 
      return filterGenres.some(genre => book.id === genre.id) 
    } else {
      return books
    }
  })

  const book = filterBookGenres.map(book => {
    return (
        <Book 
            key={book.id} 
            book={book}
            genres={genres}
            onAddGenre={handleAllGenres}
        />
    )
  })

  return (
    <div className="main-container">
      <SearchTitle 
        searchTitle={searchTitle} 
        onSearchTitle={setSearchTitle} 
      />
      <SearchGenre 
        searchGenre={searchGenre}
        onSearchGenre={setSearchGenre}
      />
      {book}
    </div>
  );
}

子组件:

export default function Book({ book, onAddGenre }) 
    const [genreTags, setGenreTags] = useState([]) 

    function handleAddGenre(e) {
        const val = {
            id: book.id,
            label: e.target.value,
        }

        if (e.key === 'Enter' && val) {
            if (genreTags.find(genre => genre.toLowerCase() === val.toLowerCase())) {
              return
            }
            setGenreTags([...genreTags, val])
            onAddGenre(val)
            e.target.value = ""
        }
    }

    return (
        <div className="book-div">
            <p>{title}</p>
            <p>Written By: {author}</p>
        </div>
        <div className="tag-div">
            <ul> 
                { genreTags && genreTags.map(tag => {
                    return <li key={uuid()}> {tag.label} </li>  
                })}
            </ul>
        </div>
        <input 
            type="text" 
            placeholder="Add a genre"
            onKeyDown={handleAddGenre} 
        />
    );
}

搜索组件:

export default function SearchTitle({ searchTitle, onSearchTitle }) {

    return (
        <div className="search">
            <input
                id="name-input" 
                placeholder="Search by title"
                value={search} 
                onChange={e => onSearch(e.target.value)} 
            />
        </div>
    );
}
export default function SearchGenre({ searchGenre, onSearchGenre }) {
    return (
        <div className="search">
            <input 
                id="tag-input"
                placeholder="Search by genre"
                value={searchGenre}
                onChange={e => onSearchTag(e.target.value)} 
            />
        </div>
    )
}

更新:搜索功能现在可以使用,但我注意到我的标签在我尝试使用任一搜索功能后消失了。例如,如果我输入搜索值并过滤图书列表,然后删除我的搜索词,我的标签就会消失。我想是因为这些书被重新渲染了?

有没有办法防止这种重新渲染或防止我的标签在玩弄我的搜索功能后消失?

所有的帮助表示赞赏。谢谢!

斯蒙罗

很难说,因为我看不到 onClick 处理程序内部发生了什么(它们位于不同的组件中)。我马上就看到了一个可能的问题(这很奇怪,考虑到你说类型是问题而不是标题搜索)。filterBooks你有book => { return title.toLowerCase()...,但应该是book => { return book.title.toLowerCase()...

此外,在此代码示例中,您没有设置setGenres. genres状态空?

编辑

有没有办法防止这种重新渲染或防止我的标签在玩我的搜索功能后消失?

是的,在我们刷新页面或卸载并重新安装Books组件之前,我们可以使用一个变通解决方案对象是可变数据结构,因此您可以改变它们以添加新键(“标签”)。即使Book对象卸载并重新安装,这些也会持续存在我们可以做到这一点handleAddGenreBook.js,像这样:

  function handleAddGenre(e) {
    const val = {
      id: book.id,
      label: e.target.value
    };

    if (e.key === "Enter" && val) {
      if (
        /**
         * Note that I made a small change here, 
         * adding 'labels' before the two toLowerCase methods
         */
        genreTags.find(
          (genre) => genre.label.toLowerCase() === val.label.toLowerCase()
        )
      ) {
        return;
      }
      /**
       * we mutate the book object here.  
       * This will persist until we reset the books state,
       * so searching doesn't make it disappear.
       */
      book.tags = book.tags ? [...book.tags, val] : [val];
      setGenreTags([...genreTags, val]);
      onAddGenre(val);
      e.target.value = "";
    }
  }

然后,我们只需要相应地更改渲染,因为它应该遍历书的新tag键以找到所有新标签

<ul>
  {book.tags &&
    book.tags.map((tag) => {
      return <li key={uuid()}> {tag.label} </li>;
  })}
</ul>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用Javascript比较两个数组相等?

比较两个数组并在javascript中对此过滤一个数组并做出反应

使用laravel比较两个数组

Vue,比较两个数组并检查结果是否匹配

合并ID上的两个数组-映射功能-Javascript

如何比较两个数组并警告结果?

在PHP中匹配两个数组的ID

比较两个数组并按对象ID删除对象

根据匹配的ID合并两个数组中的项目

如何使用张量流比较两个数组?

我可以使用JavaScript映射,过滤器来映射具有相同ID的两个数组吗?

通过JavaScript或Typescript中的ID在两个数组中搜索和计数匹配项

Javascript-使用过滤器比较两个数组,效率更高

一个对象包含两个数组。如何匹配所有数组的ID?

如何比较两个数组中的数据并在javascript中返回不匹配的数组?

如何使用两个组件通过搜索进行过滤[reactjs]

如何比较两个数组并在Clickhouse中找到数组中的匹配项(0/1)

如何使用for循环逐个元素比较两个数组?

如何使用for循环比较两个数组?

如何使用php比较相同顺序的两个数组

Reactjs 搜索/过滤功能

使用 if 循环比较两个数组

比较两个数组的 id | 反应器

如何在不使用过滤器方法的情况下根据出现的情况比较两个数组?

MongoDB 使用聚合比较两个数组 id 和更新时间

如何在 Reactjs 中使用搜索栏过滤表格行

如何通过比较两个数组中的书籍 ID 来添加书籍作者

根据嵌套的 id 过滤两个数组数据

有没有办法在这个 reactjs 代码中获取这两个数组 Id?