Only show matching string in array when using 'useMemo' in react

Viewed 459

I have an autocomplete input field and running into issues when initially hiding the output in my array. Instead of showing all my items when mounted, I just want to show the matching string. Leaving my state empty const [filteredRecipes, setFilteredRecipes] = useState(); will throw in error in my loop.

Codesanbox: https://codesandbox.io/s/quzwg?file=/App.js:251-313

Js:

export default function App() {
  const items = useMemo(
    () => ["item1", "item2", "anotheritem", "yetanotheritem", "myitem"],
    []
  );

  const [search, setSearch] = useState("");
  const [filteredRecipes, setFilteredRecipes] = useState(items);

  const handleSearchChange = event => {
    setSearch(event.target.value);
  };

  useEffect(() => {
    setFilteredRecipes(
      items.filter(el => el.toLowerCase().includes(search.toLowerCase()))
    );
  }, [search, items]);

  return (
    <div>
      <input
        type="search"
        placeholder="type here to filter"
        value={search}
        onChange={handleSearchChange}
      />
      <div>
        {filteredRecipes.map(recipe => (
          <p>{recipe}</p>
        ))}
      </div>
    </div>
  );
}
1 Answers

If I'm understanding your question correctly, in your example filteredRecipes are the autocomplete suggestions that you want to initially hide when mounting, or, making an assumption here, whenever the search value is falsey. You can do this by conditionally filtering on search state being truthy/falsey. All strings will include the empty string (''), so you want to handle this case differently.

setFilteredRecipes(
  search
    ? items.filter((el) => el.toLowerCase().includes(search.toLowerCase()))
    : []
);

Code

export default function App() {
  const items = useMemo(
    () => ["item1", "item2", "anotheritem", "yetanotheritem", "myitem"],
    []
  );

  const [search, setSearch] = useState("");
  const [filteredRecipes, setFilteredRecipes] = useState([]);

  const handleSearchChange = (event) => {
    setSearch(event.target.value);
  };

  useEffect(() => {
    setFilteredRecipes(
      search
        ? items.filter((el) => el.toLowerCase().includes(search.toLowerCase()))
        : []
    );
  }, [search, items]);

  return (
    <div>
      <input
        type="search"
        placeholder="type here to filter"
        value={search}
        onChange={handleSearchChange}
      />
      <div>
        {filteredRecipes.map((recipe) => (
          <p>{recipe}</p>
        ))}
      </div>
    </div>
  );
}

Edit only-show-matching-string-in-array-when-using-usememo-in-react

Related