I might be missing something, but doesn't this do what you need ?
import { useEffect, useState } from 'react';
const mockColors = ['white', 'blue', 'yellow', 'green', 'orange', 'purple'];
function App() {
const [search, setSearch] = useState('');
const handleInputChange = (e) => {
setSearch(e.target.value);
};
const resultantColors = useMemo(() => {
if (search == '') {
return mockColors;
} else {
return mockColors.filter((color) =>
color.toLowerCase().includes(search.toLowerCase())
);
}
}, [search]);
return (
<div style={{ border: '1px solid blue', padding: 20, margin: 20 }}>
Filter Example with UseEffect <br />
<label htmlFor="colors">Filter Color:</label>
<input
type="search"
name="search"
value={search}
id="colors"
onChange={(e) => {
handleInputChange(e);
}}
placeholder="filter colors"
/>
{resultantColors.length > 0 ? (
resultantColors.map((value, index) => (
<>
<li key={`${value} + ${index}`}>{value}</li>
</>
))
) : (
<p>No items - search existing value </p>
)}
</div>
);
}
export default App;
I moved the constants for mockColors outside of the App declaration. You should also look at debouncing the change of the search value so that it doesn't cause the memoized collars to change as frequently. There are lots of examples on SO, for example this one: https://stackoverflow.com/a/24004942/23356563