I am trying to implement a filter form. I have all the filters in a useState hook.
const [filters, setFilters] = useState({});
And then I have a fetch function that calls the api with the filters. Filtering works as expected; clicking on Apply button after all filters are set retrieves the proper records as expected.
Then there's the remove filter function. To do that I do this:
const clearFilters = () => {
setFilters({}) //tried with setFilters( () => {} ) as well
fetch();
}
The problem is filters doesn't get removed the first time, but on second click it works.
I am aware that the suggested approach is using useEffect
but the problem with this approach is that I do not want to call the fetch function every time filters
changes. I want to be able to update the view only when the Apply Filters
or 'Remove Filters` is clicked.
I tried this approach from another SO answer as well, but the behaviour is the same.
Promise.resolve()
.then(() => {
setFilterState({});
})
.then(() => {
fetch();
});
How do I achieve this?
CodePudding user response:
You could keep a state for the clearFilter and add a useEffect for that.
const App = () => {
const [clearFilterState, setClearFilterState] = useState(false);
useEffect(() => {
if(clearFilterState) {
// call your API here
setClearFilterState(false);
}
},[clearFilterState])
const clearFilter =() => {
setFilter({});
setClearFilterState(true);
}
}
CodePudding user response:
Could you have a state that handles true/false and renders the filters from the fetch-call if the state is true, and returns an initialState if the state is false?
I.e when the apply filters
is clicked, the boolean state is true and renders the filters, and when the remove filters
is clicked, the boolean state changes and the filters gets set to an initialState as {}
CodePudding user response:
You may use the react-dom flushSync
. This function takes a callback in which you can update state synchronously. Everything executed after flushSync
will have access to the updated value of the state.
Be careful anyway not to use this function too much as it may result to poor performances.
You could write your function this way:
import { flushSync } from 'react-dom';
const clearFilters = () => {
flushSync(() => {
setFilters({})
})
fetch();
}
CodePudding user response:
You can pass the filter object in the fetch function. So, the clear filter function will be as follows:
const clearFilters = () => {
setFilters({})
fetchFilter({});
}
The fetch function will be
cont fetchFilter = (filter)=> {
fetch('url', filter)
...other function's side effects
}