So here I have search functionality. Everything works fine except when an Item has not been found in the array. I have tried something with objects.Keys but it is displaying it on the render not when the Book has not been found like it should. Should I use if statement or.
import React,{useState, useEffect, useRef, useContext}from 'react' import {FaSearch} from 'react-icons/fa' import { Link, useHistory } from "react-router-dom"; import { BookContext } from '../../context/books'; import SearchBooks from './SearchBooks'; const Search = () => { const {data}= useContext(BookContext) const [searchValue, setSearchValue] = React.useState(''); const history= useHistory() const ref=useRef() function filterBooks(book) { console.log(book); if (!searchValue.length ) return false; return book.bookName?.toLowerCase().includes(searchValue.toLowerCase()); } const handleSearch = (e) => { if (ref.current && !ref.current.contains(e.target)) { setSearchValue('') } }; useEffect(() => { document.addEventListener('click', handleSearch); return () => { document.removeEventListener('click', handleSearch); }; }, []); return ( <div className='search__cont' ref={ref}> {Object.keys(data).filter(filterBooks).length === 0 &&( <div> <h3>Book not found</h3> </div> )} <SearchBooks searchValue={searchValue} setSearchValue={setSearchValue }/> {Object.keys(data) .map((key) => data[key]) .reduce((acc, curr) => acc.concat(curr), []) .filter(filterBooks) .map((book) => { return ( <> <div className='search__books' onClick={() => { history.push("/book/id", { book }); setSearchValue('') }} > {" "} {book.bookName}{" "} </div> </> ); })} </div> ) } export default Search
Advertisement
Answer
You’re filtering the category names instead of the books (data
is an object with category names as keys and books as values). You can use Object.values
and Array.prototype.flat
to get an array of all the books and then apply the filter.
const filteredBooks = Object.values(data).flat().filter(filterBooks) const searchQueryPresent = searchValue.trim().length > 0
{ searchQueryPresent && (filteredBooks.length === 0 ? ( <div>No books found</div> ) : ( filteredBooks.map((book) => { return <>{/* render books */}</> }) )) }