Reputation: 83
I'm trying to add filter functionality to my project. From a list of entries with different languages, an array of all languages is created. The user should be able to click a language and have React filter to only show entries with that language. However, I can't seem to update the entries
state properly when running the filterIt
function. If I console.log entries after running setEntries(filtered)
, the result is the same.
const Archive = () => {
const [entries, setEntries] = useState([]);
let dreamFilter = [];
//get all entries from firestore
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("entries")
.onSnapshot((snapshot) => {
const newEntries = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setEntries(newEntries);
});
return () => unsubscribe();
}, []);
//after entries are loaded, create filter of all languages for 'dream'
if (entries.length > 0) {
const categoryMap = Object.values(entries)
.reduce(
(concatedArr, item) => concatedArr.concat(Object.entries(item)),
[]
)
.reduce((result, [category, values]) => {
result[category] = result[category] || [];
result[category] = result[category].concat(values);
return result;
}, {});
dreamFilter = categoryMap.dream.filter(
(item, pos) => categoryMap.dream.indexOf(item) === pos
);
}
function filterIt(value) {
const filtered = entries.filter(entry => ({
...entry,
filtered: entry.dream.includes(value)
}));
console.log("filtered results = " + JSON.stringify(filtered));
setEntries(filtered);
return filtered;
}
return (
<>
<Navigation />
<ul>
{dreamFilter.map((language, i) => (
<li key={i}>
<a href="/" onClick={(value) => { filterIt(value); value.preventDefault(); }}>{language}</a>
</li>
))}
</ul>
<ArchiveContainer>
{entries.map((entry) => (
<div key={entry.id}>
<a href={"/entry/" + entry.id}>
<h5>{entry.id}</h5>
<p>{entry.dream}</p>
</a>
</div>
))}
</ArchiveContainer>
</>
);
}
Upvotes: 0
Views: 562
Reputation: 104
In functional component you can't update states directly. assuming here you are trying to add filtered: true/false also in entries array. array.filter is for adding or removing the object from array by returning true/false.
function filterIt(value) {
setEntries(entryList => entryList.map(item => ({
...item,
filtered: item.dream.includes(value)
})));
}
Upvotes: 0
Reputation: 2774
Filter method should return either true or false. Read more here.
If you want to convert one array to an array of another object, then use map
.
You need to modify filter method to be like this:
const filtered = entries.filter(entry => entry.dream.includes(value));
Upvotes: 1