The usePosts hook
The usePosts hook is the Next.js binding for the useFetchPosts.
The usePosts
hook fetches a collection of WordPress posts from a registered post type. Its basic usage is very simple.
Basic Usage
Assuming a src/pages/blog/[[...path]].js
route with the following content.
This example is using the optional catch-all route [[..path]].js
because we want the /blog
route to be handled by the same file.
import { usePost } from '@headstartwp/next';
const ArchivePage = () => {
const { loading, error, data } = usePosts({ per_page: 10 });
if (loading) {
return 'Loading...';
}
if (error) {
return 'error...';
}
return (
<div>
{data?.posts?.map((post) => (
<h2 key={post.id}>{post.title.rendered}</h2>
))}
</div>
);
};
The route will automatically render the latest 10 posts and you get pagination, category, tags and custom taxonomies filtering for free as the following paths will automatically map URL segments into REST API requests:
- /blog/page/2
- /blog/category/category-name
- /blog/tag/tag-name
- /blog/category/category-name/page/2
Queried Object
The usePosts
hook exposes a queriedObject
. It's similar to WordPress get_queried_object() function.
It essentially returns what's being queried for, e.g., author or category. If the current page is querying posts within a certain author, then that author object will be populated in data.queriedObject.author
. Similarly, if the current page is querying posts from a given category data.queriedObject.term
will be populated with that category.
Example:
// category-name can either come from the URL or be manually specified.
const { data } = usePosts({ taxonomy: 'category', category: 'cat-name' });
return (
<h1>Category Page: {data.queriedObject.term.name}</h1>
);
Category Archive
You can use the usePosts
hook to create a category archive route (src/pages/category/[...path].js
).
We use [...path].js
here because we do not want the /category
route to render anything.
import {
usePosts,
fetchHookData,
addHookData,
handleError,
} from '@headstartwp/next';
const CategoryPage = () => {
const { data } = usePosts({ taxonomy: 'category' });
return (
<>
<h1>Category Page: {data.queriedObject.term.name}</h1>
<ul>
{data.posts.map((post) => (
<li key={post.id}>
<Link href={post.link}>{post.title.rendered}</Link>
</li>
))}
</ul>
<Pagination pageInfo={data.pageInfo} />
</>
);
};
Archive Path Matching
When using usePosts
to create archive pages (e.g. a category archive) you can optionally enable "archive path matching" to ensure that your archive routes match the expected permalink dictated by WordPress. Without "archive path matching", your archive routes would match as long as the last segment of the url is a valid term slug.
For instance, let's take the /category/[...path].js
route above. It will match URLs like:
- /category/cat-name
- /category/parent-cat-name/cat-name
The framework, however, does not check if parent-cat-name
is the de facto parent of cat-name, and even worse, it has no way to know (without additional rest api calls) if parent-cat-name
is even a valid category.
To address this, you can pass matchArchivePath
to usePosts
to tell the framework to check the link
property of the queriedObject
, i.e if the link
property of cat-name
returned by the WordPress REST API matches the front-end path.
This setting can also be enabled in headstartwp.config.js
globally.
module.exports = {
// enable archive path mapping for all default taxonomies
customTaxonomies: (defaultTaxonomies) => {
return defaultTaxonomies.map((taxonomy) => ({ ...taxonomy, matchArchivePath: true })),
},
}
Known limitations
- It is not possible to fetch posts from more than one post type.