Reputation: 65
The problem is that if I am applying filter, filteredList will be updated based on the filter if I would like to filter it again, it will give me nothing back.
const [filteredList, setFilteredList] = useState([]);
const [searchquery, setSearchquery] = useState("");
useEffect(() => {
fetch("api/device/getall")
.then((res) => res.json())
.then(
(result) => {
setIsLoaded(true);
setFilteredList(result);
},
(error) => {
setIsLoaded(true);
setError(error);
}
);
}, []);
const FilterSearchQuery = (filteredData) => {
const filteredDevice = filteredData.filter(
(item) =>
item.deviceName
.toString()
.toLowerCase()
.indexOf(searchquery.toLowerCase()) > -1 ||
);
return filteredDevice;
};
useEffect(() => {
var filteredData = FilterDevicelocation(filteredList);
setFilteredList(filteredData);
}, [searchquery]);
Upvotes: -1
Views: 57
Reputation: 203457
Filtering an array is necessarily a reducing action. The issue is that you are reducing the state that is the "source of truth", and once reduced can never be un-reduced unless you fetch the entire state again. The issue is caused by the useEffect
hook that filters and updates the filteredList
state when the query value updates.
useEffect(() => {
var filteredData = FilterDevicelocation(filteredList);
setFilteredList(filteredData); // <-- removed array entries
}, [searchquery]);
filteredList
is your "source of truth", don't mutate it once it is set. The filtered result you want to render is what is considered derived state, meaning it is "state" that is easily derived from other state and/or props. In this case the filtered "state" is derived from the current filteredList
state array and the current searchQuery
string values. Do the filtering inline prior to rendering it.
Example:
const [list, setList] = useState([]);
const [searchQuery, setSearchQuery] = useState("");
useEffect(() => {
fetch("api/device/getall")
.then((res) => res.json())
.then((result) => {
setList(result);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setIsLoaded(true);
});
}, []);
const filteredList = useMemo(() => list.filter(
(item) =>
item.deviceName
.toString()
.toLowerCase()
.includes(searchQuery.toLowerCase())
), [list, searchQuery]);
// use the derived filteredList from here out
Upvotes: 3