This is my first project using GatsbyJS and Contentful. Right now I have several posts on the site with different Content Models. For the sake of simplicity let's say I have some Content types that are Photos and others that are Video Embeds. I am using GraphQL to fetch the posts...
I have different components for each type.
Photos (also called the PhotoSection)
const data = useStaticQuery(graphql`
query {
allContentfulImage(sort: { fields: date, order: DESC }) {
edges {
node {
image {
description
file {
url
}
}
}
}
}
}
`)
Video Embeds (also called the Film Section)
const data = useStaticQuery(graphql`
query {
allContentfulVideoEmbeds(sort: { fields: date, order: DESC }) {
edges {
node {
embedURL
}
}
}
}
`)
I then compile all of the components in another component called Blog
const Blog = () => {
return (
<div>
<AudioSection />
<FilmSection />
<PhotoSection />
</div>
)
}
export default Blog
The end product is that the posts are in descending order by date BUT they are also organized by their section / Content type. If you follow the codeblock the order is AudioSection -> FilmSection -> PhotoSection. I want them to be ordered by Date (latest first) regardless of the Content type.
Hopefully this makes sense. Not really sure what to do here?
Thank you in advance
Edit... this is post attempting what was suggested. i cut out some of the bulkier sections and but left the PhotoComponent as an example
const BlogTwo = () => {
const data = useStaticQuery(graphql`
query {
music: { bla bla bla }
videos: { bla bla bla }
images: allContentfulImage(sort: { fields: date, order: DESC }) {
nodes {
type: __typename
image {
description
file {
url
}
}
}
}
`)
const dataForDisplay = [data.music, data.images, data.videos].sort(
(a, b) => b.date - a.date
)
const componentTypeMap = {
ContentfulMusicAndArt: MusicComponent,
ContentfulImage: PhotoComponent,
ContentfulVideoEmbeds: FilmComponent,
}
const MusicComponent = () => {
return (
<div>
bla bla bla
</div>
)
}
const PhotoComponent = () => {
return (
<div className={`${blogStyles.blogDiv}`}>
<div className={`${blogStyles.blogPost} ${blogStyles.image}`}>
<img
src={data.images.nodes.image.file.url}
alt={data.images.nodes.image.description}
/>
</div>
</div>
)
}
const FilmComponent = () => {
return (
<div>
bla bla bla
</div>
)
}
return (
<div>
{dataForDisplay.map(({ type, props }) =>
React.createElement(componentTypeMap[type], props)
)}
</div>
)
}
export default BlogTwo
Instead of wrapping each content type in a WhateverSection
component, combine all three arrays of content into a single array, sort it, and then loop through the combined array rendering the relevant component for each entry.
To make this more sensible, I'm going to refactor your use of static queries by hoisting them up into the blog component, combining them, and adding GraphQL aliases to make retrieving the data less verbose.
const Blog = () => {
const data = useStaticQuery(graphql`
query {
images: allContentfulImage(sort: { fields: date, order: DESC }) {
nodes {
type: __typename
date
image {
description
file {
url
}
}
}
}
videos: allContentfulVideoEmbeds(sort: { fields: date, order: DESC }) {
nodes {
type: __typename
date
embedURL
}
}
}
`)
const dataForDisplay = [...data.images.nodes, ...data.videos.nodes].sort((a, b) => b.date - a.date)
return (
<div>
{dataForDisplay.map(({ type, ...props }) =>
React.createElement(componentTypeMap[type], props)
)}
</div>
)
}
export default Blog
const componentTypeMap = {
ContentfulImage: PhotoComponent,
ContentfulVideoEmbed: FilmComponent,
}