How to search for anything from an array of objects,?

Viewed 66

How to search for anything from an array of objects,?

const [searchInput, setSearchInput] = useState('');

 let cars = [
    {
      "color": "purple",
      "type": "minivan",
      "registration": new Date('2017-01-03'),
      "capacity": 7
    },
    {
      "color": "red",
      "type": "station wagon",
      "registration": new Date('2018-03-03'),
      "capacity": 5
    },
 
  ]


 return (
  <>

     <input type="text" onChange={(e) =>setSearchInput(e.target.value)}
    {
      cars?.filter(x => Object.values(x).includes(searchInput.toLowerCase())).map((d) =>{
         console.log(d) // nothing is consoled from here tu
        //show the data here  but nothing is showing here 
        
      })
    }

  </>
 )

No errors but the data are not showing whatsoever, what is wrong here?

4 Answers

The OP for the search needs to filter the cars array where for every car item one needs to verify whether the search value is included in some of the item's values.

Also the OP needs to come up with the meaningful custom stringification of every item's value in order to assure a valid search result.

The provided approach implements a single filter function where everything from the above mentioned is included. The filter function is aware of its this context which is the to be searched value. The latter gets provided as the filter method's 2nd thisArg parameter.

Thus a possible solution boils down to ... cars.filter(doesItemContainBoundSearch, search) ... which is proven with the next provided example code.

function stringifySearchTarget(target) {
  return (target instanceof Date)
    ? target.toISOString()
    : String(target)
}
function doesItemContainBoundSearch(item) {
  const search = this.toLowerCase();
  return Object
    .values(item)
    .some(value =>
      stringifySearchTarget(value)
        .toLowerCase()
        .includes(search)
    );
}

let cars = [{
  color: "purple",
  type: "minivan",
  registration: new Date('2017-01-03'),
  capacity: 7,
}, {
  color: "red",
  type: "station wagon",
  registration: new Date('2018-03-03'),
  capacity: 5,
}];

['o', 'a', 'ur', 'red', 'wagon', 'wagons']
  .forEach(search =>
    console.log([

      JSON.stringify(search),
      '=>',
      JSON.stringify(
      
        // the next line is everything the OP needs
        // in order to filter the `cars` array by
        // any item's value which matches the search.
        cars.filter(doesItemContainBoundSearch, search)
      ),
      
    ].join(' '))
  );
.as-console-wrapper { min-height: 100%!important; top: 0; }

Edit since the OP is in need of the correct react render code

Filtering and rendering in react according to the OP's provided sandbox code would be ...

cars
  .filter(doesItemContainBoundSearch, searchInput)
  .map(car => (
    <tr>
      <td>{ car.color }</td>
      <td>{ car.type }</td>
      <td>{ car.capacity }</td>
    </tr>
  ))

or

cars
  .filter(doesItemContainBoundSearch, searchInput)
  .map(({ color, type, capacity }) => (
    <tr>
      <td>{ color }</td>
      <td>{ type }</td>
      <td>{ capacity }</td>
    </tr>
  ))
  return (
    <>
      <input type="text" onChange={(e) => setSearchInput(e.target.value)} />
      <table>
        <tbody>
          <tr>
            <td>color</td>
            <td>type</td>
            <td>capacity</td>
          </tr>
          {searchInput ?
            <>
              {
                cars?.map((car) => (
                  Object.values(car).includes(searchInput?.toLowerCase()) &&
                  <tr>
                  <td>{car.color}</td>
                  <td>{car.type}</td>
                  <td>{car.capacity}</td>
                </tr>
                ))
              }
            </>
            :
            <>
              {cars?.map((car) => (
                <tr>
                  <td>{car.color}</td>
                  <td>{car.type}</td>
                  <td>{car.capacity}</td>
                </tr>
              ))}
            </>
          }
        </tbody>
      </table>

    </>
  )

}

Try the function filterCars below your cars array.

const filterCars = cars.filter(car => {
    if (!searchInput) {
      return cars
    }
    return car.color.includes(searchInput.toLowerCase()) || car.type.includes(searchInput.toLowerCase())
  })

Then your return statement,

return (
  <div>
   {
    filterCars.map(car => (
     <p>{car.color}</p>
     <p>{car.type}</p>
   )}
  </div>
)

Note: I excluded your input element because it's fine, and should work.

import React, {useState} from "react";
import "./style.css";

export default function App() {
  const [searchInput, setSearchInput] = useState("");
  let cars = [
    {
      "color": "purple",
      "type": "minivan",
      "registration": new Date('2017-01-03'),
      "capacity": 7
    },
    {
      "color": "red",
      "type": "station wagon",
      "registration": new Date('2018-03-03'),
      "capacity": 5
    },
 
  ];
  return (
    <div>
      <input type="text" onChange={e=> setSearchInput(e.target.value)}/>
      {
      cars?.filter(x => Object.values(x).includes(searchInput.toLowerCase())).map((d) =>{
         console.log(d) // nothing is consoled from here tu
        return <span key={d.registration}>{d.color}</span>

        
      })
    }
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

Related