Houda Boukhobza
Houda Boukhobza

Reputation: 33

My search bar React does not return any results

I've added a search bar to my React-Firebase Dashboard.As a result, the search bar is displayed with the table of clients stored in Cloud Firestore, when I enter a text in the search bar It returns an empty table even if that word exists in the table.

PS: Both of the Results are shown below in screenshots

The table initially rendered

table after writing anything in the search bar

Customer.js

import React, { Fragment, useState } from "react";
import { Avatar } from '@material-ui/core';
import PageTitle from "../../../../layouts/PageTitle";
import { Dropdown, Table } from "react-bootstrap";
import { fire } from "../../../../../fire";
import { firestore } from "../../../../../fire";
import { collection, query, where } from "../../../../../fire"; 
import App from "../../../../../App";

export default class Recipe extends React.Component {

state = {
  searchTerm : "",
  Users: []
  
 }


  constructor(props){
  super(props);   
 }
  searchByTerm = (value) => {
  this.setState({searchTerm : value});
 }
  componentDidMount() {
 firestore.collection("Users").get().then((querySnapshot) => {
    let User = []
    querySnapshot.forEach((doc) => {
    console.log(`${doc.id} => ${doc.data().lastn}`);
    User.push({   
    id : doc.id,
    data: doc.data()})
    });
    this.setState({Users : User})
  });  
     }    

   delete = (id) => {
     console.log(id)
     firestore.collection("Users").doc(id).delete().then(() => {
       console.log("Document successfully deleted!");
       this.props.history.push("#")
     }).catch((error) => {console.error("Error removing document: ", 
   error);
     });
  }




  render() {



  return (
  <Fragment>  
         
    
    <div className="col-12">
    <div className="card">
    <div className="card-header">
    <div className="input-group search-area d-lg-inline-flex d-none mr- 
          5">
                       <input
                          type="text"
                          className="form-control"
                          placeholder="Search here"
                          onChange ={(e) => {
                             this.searchByTerm(e.target.value);
                           
                       }}
                       
                           />
                       
                       <div className="input-group-append">
                          <span className="input-group-text" 
                          >
                             <svg
                                width={20}
                                height={20}
                                viewBox="0 0 24 24"
                                fill="none"
                                xmlns="http://www.w3.org/2000/svg"
                             >
                                <path
                                   d="M23.7871 22.7761L17.9548 16.9437C19.5193 15.145 20.4665 12.7982 20.4665 10.2333C20.4665 4.58714 15.8741 0 10.2333 0C4.58714 0 0 4.59246 0 10.2333C0 15.8741 4.59246 20.4665 10.2333 20.4665C12.7982 20.4665 15.145 19.5193 16.9437 17.9548L22.7761 23.7871C22.9144 23.9255 23.1007 24 23.2816 24C23.4625 24 23.6488 23.9308 23.7871 23.7871C24.0639 23.5104 24.0639 23.0528 23.7871 22.7761ZM1.43149 10.2333C1.43149 5.38004 5.38004 1.43681 10.2279 1.43681C15.0812 1.43681 19.0244 5.38537 19.0244 10.2333C19.0244 15.0812 15.0812 19.035 10.2279 19.035C5.38004 19.035 1.43149 15.0865 1.43149 10.2333Z"
                                   fill="#A4A4A4"
                                />
                             </svg>
                          </span>
                       </div>  </div>
    <h4 className="card-title">Customer List </h4>
        </div> 
        <div className="card-body">      
        <Table responsive className="w-100">
        <div id="example_wrapper" className="dataTables_wrapper">
        <table id="example" className="display w-100 dataTable">
        <thead>
                       <tr role="row">
                            
                               
                                <th>Avatar</th>
                                <th>Email</th>
                                <th>Firstname</th>
                                <th>Lastname</th>
                                <th>PhoneNumber</th>
                               
                                {/* <th className="pl-5 width200">
                                Billing Address
                             </th> */}
                             <th>Action</th>
                          
                          </tr>
                               
                             
                          </thead>
                          <tbody>
                         
                             {this.state.Users.filter( (val) =>{
                                const { email = "", firstname = "" } = val;
                                // console.log(this.state.searchTerm);
                                if (this.state.searchTerm === "") {
                                   return val;
                                 } else if (
                                   email.toLowerCase().includes(this.state.searchTerm.toLowerCase()) ||
                                   firstname.toLowerCase().includes(this.state.searchTerm.toLowerCase())
                                 ) {
                                   return val;
                                 }
                                 
                             }).map(data => {

                                return (
                                   <tr>
                                      <td> <Avatar className ="rounded-circle img-fluid" src={data.data.avatar}/> </td>
                                      
                                      <td>{data.data.email}</td>
                                      <td>{data.data.firstname}</td>
                                      <td>{data.data.datalastname}</td>
                                      <td>{data.data.phonenumber}</td>
                                        
                                       <td>
                                                     <div
                                                     className="btn btn-danger shadow btn-xs sharp" onClick ={this.delete.bind(this, data.id)}
                                                  >
                                                     <i className="fa fa-trash"></i> </div></td>                
                                 </tr>
                                );

                             })}
                          </tbody>
                       </table>
                       </div>
                    </Table>
                 </div>
              </div>
           </div>
    
     </Fragment>
  );
       };
         };

Upvotes: 2

Views: 472

Answers (1)

Drew Reese
Drew Reese

Reputation: 203393

Array.prototype.filter callback should be returning a boolean, not the element being iterated over.

This is how I suggest rewriting your filter function: if there is no search term (i.e. falsey) then return true to indicate all elements iterated over should be return, otherwise, return the result of the comparison.

const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();

...

Users.filter((val) => {
  const { data: { email = "", firstname = "" } = {} } = val;
  
  if (term) {
    return (
      email.toLowerCase().includes(term) ||
      firstname.toLowerCase().includes(term)
    );
  }

  return true;
})

A slightly more succinct version could be written as follows:

const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();

...

Users.filter(({ data: { email = "", firstname = "" } = {} }) =>
  term ? email.concat(firstname).toLowerCase().includes(term) : true
)

Update

After you've stated that you implemented my suggestions and it's still not working I took a closer look at what you are rendering and noticed that in the .map callback you reference each field (email, firstname, etc...) from a data property on each element. Since it seems you are able to render your data when no filter is being applied I'll assume this structure to be correct. As such then, the .filter callback needs to also reference the nested field properties from a data property. I've updated the above code snippets.

Upvotes: 1

Related Questions