I'm building a Gutenberg block that that groups posts and displays them in sets of 2 or 3, alternating between the two configurations. This is the code I came up (some code omitted for brevity):
const { posts, hasPostsResolved } = useSelect(select => {
const query = {
order: 'asc',
orderby: 'title',
status: 'publish',
per_page: 10,
};
return {
posts: select('core').getEntityRecords('postType', 'post', query),
hasPostsResolved: select('core').hasFinishedResolution('getEntityRecords', ['postType', 'post', query]),
}
}, []);
const displayPosts = (posts) => {
var posts_per_slide = 3;
return (
<>
{posts.map((post, index) => {
if (index % posts_per_slide === 0) {
posts_per_slide = (posts_per_slide === 3) ? 2 : 3;
return (
<div key={index / posts_per_slide} className={`post-group posts-${posts_per_slide}`}>
{posts.slice(index, index + posts_per_slide).map((groupedPost, groupIndex) => (
<article
id={`post-${groupedPost.id}`}
className="wp-block-posts-carousel__post"
key={index + groupIndex}
>
<div className="wp-block-posts-carousel__post-thumbnail">
<img src="https://placehold.co/1000x700" width="1000" height="700" />
<h2 className="wp-block-posts-carousel__post-title">
{groupedPost.title.rendered
? decodeEntities(groupedPost.title.rendered)
: __('(no title)')}
</h2>
</div>
</article>
))}
</div>
);
}
return null;
})}
</>
);
};
return (
<>
<div {...blockProps}>
{!hasPostsResolved &&
<Spinner />
}
{hasPostsResolved && posts?.length === 0 &&
<p>
{__('No posts found')}
</p>
}
{hasPostsResolved && posts?.length > 0 &&
<>
<div class="wp-block-posts-carousel__posts">
{displayPosts(posts)}
</div>
</>
}
</div>
</>
);
But it's not working as expected, because some of the posts are repeated in multiple posts groups, and also, I need the first group to contain three posts, not two.
Any help would be appreciated.
I managed to find a solution by grouping the posts in arrays of 3 and 2 BEFORE rendering them:
const displayPosts = (posts) => {
// Group posts in sets of three and two alternately.
var groupedPosts = [];
for (let i = 0; i < posts.length; i += 5) {
groupedPosts.push(posts.slice(i, i + 3));
groupedPosts.push(posts.slice(i + 3, i + 5));
}
return (
<>
{groupedPosts.map((group, index) => (
<div key={index} className={`post-group posts-${group.length}`}>
{group.map((post, subIndex) => (
<article key={subIndex} id={`post-${post.id}`} className="wp-block-jn-post-carousel__post">
<div className="wp-block-jn-post-carousel__post-thumbnail">
<img src="https://placehold.co/1000x700" width="1000" height="700" />
<h2 className="wp-block-jn-post-carousel__post-title">
{post.title.rendered
? decodeEntities(post.title.rendered)
: __('(no title)')}
</h2>
</div>
</article>
))}
</div>
))}
</>
);
};