looking for a bit of advice if possible? I'm trying to setup a list of tags that can be used for filtering in a Gatsby app that uses Contentful and its tags implementation.
I'm referring to a tutorials video that gave me the idea, but the graphql structure in mine differs and appears to contain a number of objects
I keep ending up with an object which is making it either difficult or not possible to map over the resulting items. The graphql hook is like so:
import { graphql, useStaticQuery } from "gatsby";
const useAllStories = () => {
const {
allContentfulStories: { nodes },
} = useStaticQuery(graphql`
query allStoriesLinksQuery {
allContentfulStories {
nodes {
title
gatsbyPath(filePath: "/journal/{contentfulStories.slug}")
createdAt(formatString: "MMMM DD, YYYY")
metadata {
tags {
name
contentful_id
}
}
}
}
}
`);
return nodes;
};
export default useAllStories;
And the component looks like:
import React from "react";
import useAllStories from "../hooks/use-all-stories";
const TagFilter = () => {
const allStories = useAllStories();
const tagMeta = allStories
.map((item) => {
return item.metadata.tags;
})
.flat()
.reduce((acc, tag) => {
// Check if exisiting
// if yes, increment
const exisiting = acc[tag.contentful_id];
if (exisiting) {
exisiting.count += 1;
} else {
//otherwise new entry
acc[tag.contentful_id] = {
id: tag.contentful_id,
name: tag.name,
count: 1,
};
}
return acc;
}, {});
// This is returning an object
console.log(tagMeta)
return (
<div>
<div>
{/* {tagMeta.forEach((item) => {
item.map((itm) => {
<p>{itm.name}</p>;
});
})} */}
</div>
</div>
);
};
export default TagFilter;
I'm at a bit of a loss here of how I need to convert this effectively. Currently, it returns in a structure similar to releaseNotes: {id: 'releaseNotes', name: 'Release Notes', count: 2}. But because of it returning an object I have no ability to map/forEach over it.
Could someone point out where I could simplify this?
I'm not familiar with graphql or gatsby, but it sounds like you want to iterate over the elements of a object. There are a few ways to do this, one is Object.entries which will essentially provide an array with the elements being arrays of key value pairs from the object. It looks like the key might be redundant for your case, so possibly Object.values might be more suitable.
You might simply be able to do something like:
{Object.values(tagMeta).map((item) => (
<p key={item.id}>{item.name}</p>
))}