-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for pagination and categories/tags #33
Comments
Not yet. This would be very useful. I think how it should work is that I think ideally there would be a Thoughts? |
On the writing side ( Pages are a little tricky, and needed (out of the box?), look at the gatsby-starter-documentation and its nested pages structure that is also suitable for organizing topics/layouts in a blog/site, all of those "sub trees" should have their own pagination too. |
Right, pagination is tricky and it'd be nice to put that logic in its own plugin. Here's an idea for how plugins could be structured. paginationPlugin: [{
blog: {
pathPattern: /^\/blog/.*/,
outputPathPattern: "/blog/{pageIndex}/"
process: (pages) => { // function is called with all that pages that matches the `pathPattern`
// Order pages then return object like { 1: [// pages], 2: [// pages], 3: [// pages] }
},
docs: { // Do something similar here for docs }}
] Gatsby would calculate ahead of time the pagination. Then for each possible output page (e.g. |
We need to start brainstorming for a proper plugin API. |
So one thought here is to let pages use the RoutePattern from React-Router. So a blog index at |
Category/tag pages could do something similar e.g. |
hi. |
Not yet... |
Hey there! :) Could you please outline the steps (files to touch, etc) in order to implement a tags feature? I'm thinking about contributing, but as I'm not familiar with the codebase, could need a few hints where to start. |
@funkybunky this is actually something I'm working on right now :-) to make it happen will require a fairly big change so not something that's easy to describe here. If you need tags in the short-term, the easiest thing to do is to just manually (or programmatically) create pages for each tag e.g. |
@KyleAMathews thanks for the follow-up! Cool to know that you're working on it. If you need any help, let me know :) |
Will be releasing initial version soonish — would love feedback + help On Sat, Aug 13, 2016 at 2:14 PM Marcus Kleppe notifications@github.com
|
Don't suppose any conclusion was reached regarding URL parameters / wildcard routes? I find myself needing such a feature for minified error messages. 😄 |
@bvaughn — couldn't you just create the pages normally? Or is the data not known at build time and you dynamically fetch it? If that's the case, you can create client only pages https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#creating-client-only-routes |
No, I could generate part of the routes "normally" (eg the error codes themselves) but part is also dynamic (eg the name of a component or variable, eg this). Thanks for the client-only route link. I couldn't find that earlier when I was searching. Are there any drawbacks (in terms of performance, etc) to using this approach? There's no async fetching or anything, just parameter-injection via URL. |
Oh ok, just use the |
Sure, sure. I just didn't know what the |
I've only been evaluating Gatsby for a day by using the gatsby-source-wordpress plugin. For post index pages (list of ten posts and pagination links), do I have to get all the wordpress posts then render a static page for every 10 posts in the gatsby-node.js file? |
@benjamingeorge basically. |
Sorry to circle back after such a delay. I got side-tracked by 16 beta! 😄 I think I created a client only route as described in the docs you shared: exports.onCreatePage = async ({ page, boundActionCreators }) => {
const { createPage } = boundActionCreators;
return new Promise((resolve, reject) => {
if (page.path.includes('docs/error-decoder.html')) {
page.matchPath = 'docs/error-decoder.html?:args';
page.context.slug = 'docs/error-decoder.html';
createPage(page);
}
resolve();
})
}; After doing this, the route almost works but not quite:
Unfortunately, the last one is the one I specifically need to work for backwards compatibility with the React error page. I've tried a few variations for the page.matchPath = 'docs/error-decoder.html?invariant=:invariant&args=:args';
page.matchPath = 'docs/error-decoder.html?:args';
page.matchPath = 'docs/error-decoder.html:args';
page.matchPath = 'docs/error-decoder.html*';
page.matchPattern = /docs\/error-decoder\.html.+/; Am I perhaps misunderstanding something or overlooking? 😄 Edit For what it's worth, I just updated to the latest Gatsby (and co) versions to rule out something that had already been fixed. |
Hmm dunno. This is a react-router function under the hood so I'd check their docs on this. |
Is this really a For example, check out this bin: https://www.webpackbin.com/bins/-KrgnTIAd88pSOiSeNQK In it, I define a route: <Route path="/foo.html" component={Foo}/> And that route automatically works with query params (eg page.matchPath = 'docs/error-decoder.html';
page.matchPath = 'docs/error-decoder.html?invariant=:invariant&args=:args';
page.matchPath = 'docs/error-decoder.html?:args';
page.matchPath = 'docs/error-decoder.html:args';
page.matchPath = 'docs/error-decoder.html*';
page.matchPattern = /docs\/error-decoder\.html.+/; // This one I just took a guess at Or rather, they all almost work (as described above) but not the one format I need. 😁 |
You're right, I shouldn't have said we're vanilla react router matching. If you look in here you'll probably find where things are going bad. https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/find-page.js |
Cool! Thanks for the pointer (and the prompt response, as always). That function doesn't seem to be invoked though when I try to load |
I tried renaming So I've just specified a Next I tried loading the URL, The Stepping further, the regular expression that's generated inside of I think maybe Edit: I can work around this particular issue with |
Ah this could be it. We only pass the pathname to findPage in https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/production-app.js |
Yeah. I'm just a bit baffled still by the specific issue with this page. I can make the |
I think the other half of my issue (the instant-404) has to do with the file extension in the path. // 404s when loading "/foo/bar.baz" and "/foo/bar.baz?qux"
// Doesn't even execute find-page.js
page.matchPath = "/foo/bar.baz:qux?";
// This on the other hand does execute find-page.js
// Successfully matches "/foo/bar" and "/foo/bar?baz"
page.matchPath = "/foo/bar:baz?"; Breaking this down further has helped a lot. The first half of the problem was the dynamic token bit needing a "?" suffix. The second half seems to be the file-extension and I'm not yet sure how to handle that. Maybe Gatsby (or whatever is serving up the localhost env) is treating potentially real/static files (things with extensions) differently somehow? Escaping the "." (eg |
I think the next (last?) thing to figure out is why file extensions in the path cause inconsistent routing behavior.
The above routing behavior block things before Edit: It looks like things are going wrong in |
There's now https://github.com/pixelstew/gatsby-paginate which is pretty awesome. Closing this issue as it's old and not active. |
That package is unmaintained and buggy. IMO pagination should be built-in somehow. It's a thing that almost every project will be using. |
For people interested in a static site generator that works with React and provide pagination built-in, you should take a look to Phenomic (here https://phenomic.io/en/packages/preset-react-app/docs/getting-started/05/#immutable-pagination) The goal of my comment is to show that pagination can (and should) be taken seriously when it comes to SSG. Phenomic decided to have this built-in since day 1. I am not trying to be a dick by saying "come, my ssg is better" (cause it's probably not) but more "it can be done, you should do it". |
Stop hijacking threads please. Your comment brings no value. Update: Why are you responding with a "confused" emoji? What you're doing here is very unprofessional. Going out to direct "competition" communities and posting your links all over the place. Especially on issues where we're trying to make the software better and collaborate on things. That's a shameless plug that is nowhere tangential with the issue being discussed. It's completely parallel and designed to suck members over to your product. |
I've just published https://github.com/kbariotis/gatsby-plugin-paginate which is a Gatsby plugin that does pretty much what |
Reading through this thread, I'm not positive what I'm trying to do is possible or if there is a solution available for it that I'm just not finding... I'm building out a blog using gatsby with content pulled from Prismic. Each blog post has an author and tag related to them via Prismic Content Relationship. My goal is to dynamically create pages via gatsby-node for the author and tag pages that also include pagination for their related blog posts. Prismic unfortunately doesn't seem to create a relationship going both ways, so I have to find related blog posts by doing a graphql query on my allPrismicBlog filtering for author uid. example of what I'm trying to create - I have the following in my gatsby-node:
I'm getting the error TypeError: Cannot read property 'page' of undefined I'm not sure if what I'm trying to do here is the right direction or if I'm missing something important. Any help would be greatly appreciated. |
@clkent i think the issue lies here: const authorPosts = graphql(`
{
allPrismicBlog(filter: { data: { author: { uid: { eq: ${authorUid} } } } }) {
edges {
node {
uid
}
}
}
`); The graphql queries will not run synchronously, they run in a async fashion. Meaning that the code you have there, it will iterate each element in the foreach, not waiting for anything, basically taking a approach of "fire and forget" and by that that i mean it triggers a graphql query and it's not capturing either errors or results. const result = await graphql(`
{
AuthorInformation:allPrismicAuthor {
edges {
node {
uid
}
}
}
BlogPosts: allPrismicBlog {
......
}
}
}
`); then you have both bits of data available in one query and you paginate the data based on what you have available already. Alternatively you probably would have to use promise all to wait for it and then proceed with the pagination. |
@jonniebigodes thanks for your response... is there some way to use the returned Regardless of the query I am still left with the issue of dynamically creating the author pages from the allPrismicAuthor query results with pagination for each based on the number of Blog Posts they have. Even if I hardcode in the number of pages, my logic above still doesn't work. |
Figured out a solution and wanted to share here in case anyone else runs into something similar in the future. Instead of trying to query for the blog posts with the author uid and dealing with the async nature of the two queries I am just filtering the blogList and creating pages based on that. There's probably several ways to improve this code during a refactor but wanted to share what I got working.
|
@clkent glad that you managed to work it out, you can even improve it and make it more efficient by merging both queries into one with aliasing, removing the need of having one extra graphql and have to await for it to resolve and get the results back. {
allBlogPosts:allPrismicBlog(sort: { fields: [data___blog_post_date], order: DESC }, limit: 1000) {
edges {
node {
uid
data {
author {
uid
}
tag {
uid
}
}
}
}
}
allAuthors:allPrismicAuthor {
edges {
node {
uid
}
}
}
} Also as a good practice you could introduce a sanity check for errors: const blogList=.....
if (blogLIst.errors){
throw new Error('some error happened')
return
} |
@clkent amazing, your solution worked for me, thank you! 🙌 good ol' |
I haven't dig much about it, does gatsby have built in support for pagination and categories/tags?
i.e.
http://blog.ghost.org/page/2/
http://blog.ghost.org/tag/writing/
That would sum up in two special routes that accept a wildcard * after the main path.
/page/*/
/tag/*/
While playing with gatsy I also found beneficial to leave the main route "themable", I mean
/page/_template.jsx
/tag/_template.jsx
As it would work for WordPress (use the custom page if found, or pick the default one).
Another different scenario is the 404 page that should be supported by React Router.
The text was updated successfully, but these errors were encountered: