I am working on a React JS based UI and facing an issue wiht data .
- I fetch data from an API and store it in an initial value by using useState hook.
- Then I use useEffect to store it in 'lists' via setLists()
const [lists, setLists] = useState([]);
useEffect(()=>{
const url = "https://domain/api/all";
fetch(url).then(response => response.json()).then(response=> {
setLists(response.json.list);
});
- Now I am able to use map to enter data in a table
- Lists is an array object that has multiple values in it and I want t filter the table based on age and country
let [ageList, setAgeList] = useState([]);
let [countryList, setcoutryList] = useState([]);
useEffect(()=>{
var newList = lists.filter(e=> e.age === age);
setList(newList)
},[age])
useEffect(()=>{
setlist(lists.filter(e=> e.country === country))
},[country])
With this method first attempt of filter works fine by both Age and Country but when I change the value of the filter for age or country then I get empty array which is expected as the new lists variable has entered with last filtered country/age
How can I get over this?
CodePudding user response:
As you noticed, when you overwrite your previous state with the filtered state, you lose the previous state forever. The solution here is to keep the initial value of lists
and create a new variable for your filtered lists. Something like this:
const [lists, setLists] = useState([]);
const [ageFilter, setAgeFilter] = useState("");
const [countryFilter, setcountryFilter] = useState("");
const url = "https://domain/api/all";
fetch(url)
.then(response => response.json())
.then(response=> {
setLists(response.json.list);
});
let filteredByCountryAndAge = listfilter((listItem) => {
return (listItem.country === countryFilter && listItem.age === ageFilter);
});
(or however else you are filtering it).
The point being, do not change the value of lists
after it is set with the entire list. When filtering, assign the criteria by which you are filtering to state variables, but assign the filtered data to a variable—NOT a state variable.
CodePudding user response:
Do you have control over the fetched data? If so, the obvious solution would be to change the datamodel server side.
If not, I would suggest storing the initial response in a mutable object from useRef
.
Edit
const [lists, setLists] = useState([]);
const cache = useRef([]);
useEffect(()=>{
const url = "https://domain/api/all";
fetch(url).then(response => response.json()).then(response=> {
cache.current = response.json.list;
setLists(response.json.list);
});
});