Reputation: 183
So i have a const with an array of objects, named "data", a state that receive that data so I can update the screen when I change it, and I have a function that filter that data.
Every time that the user change the state of an HTML select, I trigger a function named handleChange that calls the filter function, so the user user can see the filtered content. The problem is that I want to reset the state that receives the data, with the original data before filtering it, so if the user change one of the selects, it filter based on the original data, not the previous changed one, but when I try to update the state with the const data value, it doesn't work.
Here is my code
const [list, setList] = useState<IData[]>([...data]);
const [filter, setFilter] = useState<IFilter>({
name: "",
color: "",
date: "",
});
function handleChange(
key: keyof IData,
event: React.ChangeEvent<{ value: string }>
): void {
const newFilter = { ...filter };
newFilter[key as keyof IData] = event.target.value;
setList([...data]); // reset the data
setFilter({ ...newFilter }); // set the filter value
filterList();
}
function filterList(): void {
const keys = Object.keys(filter) as Array<keyof IData>;
keys.forEach((key: keyof IData) => {
if (filter[key]) {
const newList = list.filter((item: IData) => item[key] === filter[key]);
setList([...newList]);
}
});
}
the problem is here
setList([...data]); // reset the data
setFilter({ ...newFilter }); // set the filter value
filterList();
apparently, when the filterList happens, the list state is not yet restarted with the data value, since if I console log it inside filterList(), it return me only the list that was previous filtered. Is there a way for me to make sure that the setList happens before filtering, so I'm sure that the list that is filtered is always based on the initial value?
Upvotes: 1
Views: 114
Reputation: 5036
You can access the updated values inside useEffect
(more about useEffect), so instead of calling filterList()
directly inside the handler you move it inside the hook:
React.useEffect(()=>{filterList();},[list,filter])
Alternatively, you can pass the values as parameters to the function, after you updated the state with them
filterList(newList, newFilter)
UPDATE
As you update list
inside filterList
you'll need some sort of a flag to indicate if you need to filter of not (I'd use useRef
). Note that it would be preferable to pass parameters into filterList
instead, because this way there will be one less rendering cycle. Here is a simplified example of how both can work, let me know if they make sense : https://jsfiddle.net/6xoeqkr3/
Upvotes: 1