Search code examples
javascriptreactjssearchbar

How to add function to "X" icon in Material UI Searchbar?


I have the following code:

import SearchBar from "material-ui-search-bar";

const data = [
  {
    name: "Jane"
  },
  {
    name: "Mark"
  },
  {
    name: "Jason"
  }
];
export default function App() {
  const [results, setResults] = useState();

  const filteredResults = data.filter((item) => {
    return Object.keys(item)?.some((key) => {
      return item[key].includes(results?.toLowerCase());
    });
  });
  return (
    <div className="App">
      <SearchBar
        value={results}
        onChange={(value) => setResults(value)}
        placeholder="Please enter name..."
      />

      {filteredResults.map((item) => {
        return <li>{item.name}</li>;
      })}
    </div>
  );
}

codesandbox

when I delete name from search bar using delete keyboard all names from data are displayed below the search bar, but if I click X button, it clears the search bar but doesn't display all names. Is there a way to add a function to this X button so when I click it, it acts the same way as delete keyboard?


Solution

  • You can pass a function to the onCancelSearch prop to reset the results state variable.

    <SearchBar
      value={results}
      onChange={(value) => setResults(value)}
      onCancelSearch={() => setResults('')}
    />
    

    Suggestions

    It's better to initialize results with an empty string. You can now remove the ? in results?.toLowerCase() since results will never be nullish (undefined or null).

    const [results, setResults] = useState('')
    

    You should pass the key prop to the li element. You can add an id property to the items array to use as the key or use the item index.

    {
      filteredResults.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))
    }
    

    And there are a couple of issues with the filtering logic.

    • You're converting the search query to lowercase but not the name. In your example, if you search for 'ja', nothing would show up even though matches exist (Jane and Jason).

    • filteredResults will throw an error if any of the object values do not have the includes method (You can reproduce the issue by adding a numeric id field to the array items). You could fix it by using a searchableKeys array to only perform the search in specific fields.

    const searchableKeys = ['name']
    
    const filteredResults = data.filter((item) =>
      searchableKeys.some((key) =>
        item[key].toLowerCase().includes(results.toLowerCase())
      )
    )
    

    Edit material ui search bar


    I would recommend renaming results to query or searchQuery for clarity.