{"data":{"markdownRemark":{"html":"<p>How do you create paginated pages in Gatsby? You might have many blog posts and want to show 10 per page. Do you need a Gatsby pagination plugin?</p>\n<blockquote>\n<p><strong>tl;dr</strong> - Don't use a plugin (yet). Call <code class=\"language-text\">createPage()</code> and pass limit and skip in context. Use lodash <code class=\"language-text\">_.times()</code> and some custom logic.</p>\n</blockquote>\n<h2>What is pagination?</h2>\n<p>You have 107 blog posts. You want to show 10 posts per page. That makes 11 pages. The pages should be <code class=\"language-text\">/blog</code>, then <code class=\"language-text\">/blog/2</code>, <code class=\"language-text\">/blog/3</code>, etc. Each page should have a link to to the next and previous pages (where appropriate).</p>\n<p>For example:</p>\n<ul>\n<li><code class=\"language-text\">/blog</code> links to <code class=\"language-text\">/blog/2/</code> as the next page</li>\n<li><code class=\"language-text\">/blog/2/</code> links to <code class=\"language-text\">/blog</code> as the previous page and <code class=\"language-text\">/blog/3</code> as the next page</li>\n</ul>\n<p>The first page has no previous link. The last page has no next link.</p>\n<h2>Pages in Gatsby</h2>\n<p>Pagination is not part of Gatsby. It doesn't need to be. You create pages just as normal via <code class=\"language-text\">createPage()</code>. Paginated pages do not need any special treatment.</p>\n<h2>Pages and Pages</h2>\n<p>The terms are confusing. Page 1 and a Gatsby Page. We'll call Gatsby pages a \"page\". We'll call page 1, page 2, etc \"paginated pages\". A paginated page is also a page!</p>\n<h2>Blog posts</h2>\n<p>In this article we'll talk about blog posts. The same logic applies to any other type of page. We'll show some examples later of applying the same to category or tag pages.</p>\n<h2>Create pages in <code class=\"language-text\">gatsby-node.js</code></h2>\n<p>In summary.</p>\n<ul>\n<li>Fetch data</li>\n<li>Calculate how many pages there should be</li>\n<li>\n<p>Create each page</p>\n<ul>\n<li>Pass skip and limit</li>\n<li>Pass some other pagination variables</li>\n</ul>\n</li>\n</ul>\n<h2>How many paginated pages?</h2>\n<p>If you have 107 blog posts and 10 per page, you need 11 paginated pages. With 107 blog posts and 15 per page, 8 paginated pages.</p>\n<p>In javascript, that is:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> paginatedPagesCount <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">ceil</span><span class=\"token punctuation\">(</span>blogPostsCount <span class=\"token operator\">/</span> blogPostsPerPaginatedPage<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2>Helpers</h2>\n<p>Creating the paths like <code class=\"language-text\">/blog</code> and <code class=\"language-text\">/blog/2</code> requires a little logic. We can put all of this into a helper function. You can define it at the top scope in <code class=\"language-text\">gatsby-node.js</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">paginationPath</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">,</span> page<span class=\"token punctuation\">,</span> totalPages<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>page <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> path\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>page <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span> <span class=\"token operator\">||</span> page <span class=\"token operator\">>=</span> totalPages<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">''</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token template-string\"><span class=\"token string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>path<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>page <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">`</span></span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We need to know the total number of pages in order to know which is the last page. If we have 11 pages the link for page 12 is an empty string. There is no page 12!</p>\n<h2>Creating paginated pages</h2>\n<p>We'll assume you've already fetched your blog posts as normal inside <code class=\"language-text\">gatsby-node.js</code>. The blog posts are in an array <code class=\"language-text\">blogPosts</code>.</p>\n<p>Then you can create pages like this.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// How many posts do we have?</span>\n<span class=\"token keyword\">const</span> blogPostsCount <span class=\"token operator\">=</span> blogPosts<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// How many posts per paginated page?</span>\n<span class=\"token keyword\">const</span> blogPostsPerPaginatedPage <span class=\"token operator\">=</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// How many paginated pages do we need?</span>\n<span class=\"token keyword\">const</span> <span class=\"token keyword\">const</span> paginatedPagesCount <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">ceil</span><span class=\"token punctuation\">(</span>blogPostsCount <span class=\"token operator\">/</span> blogPostsPerPaginatedPage<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Create each paginated page</span>\n_<span class=\"token punctuation\">.</span><span class=\"token function\">times</span><span class=\"token punctuation\">(</span>paginatedPagesCount<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>index<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">createPage</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Calculate the path for this page like `/blog`, `/blog/2`</span>\n    path<span class=\"token punctuation\">:</span> <span class=\"token function\">paginationPath</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/blog'</span><span class=\"token punctuation\">,</span> index<span class=\"token punctuation\">,</span> paginatedPagesCount<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// Set the component as normal</span>\n    component<span class=\"token punctuation\">:</span> componentPath<span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// Pass the following context to the component</span>\n    context<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Skip this number of posts from the beginning</span>\n      skip<span class=\"token punctuation\">:</span> index <span class=\"token operator\">*</span> blogPostsPerPaginatedPage<span class=\"token punctuation\">,</span>\n      <span class=\"token comment\">// How many posts to show on this paginated page</span>\n      limit<span class=\"token punctuation\">:</span> blogPostsPerPaginatedPage<span class=\"token punctuation\">,</span>\n      <span class=\"token comment\">// How many paginated pages there are in total</span>\n      paginatedPagesCount<span class=\"token punctuation\">,</span>\n      <span class=\"token comment\">// The path to the previous paginated page (or an empty string)</span>\n      prevPath<span class=\"token punctuation\">:</span> <span class=\"token function\">paginationPath</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/blog'</span><span class=\"token punctuation\">,</span> index <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> paginatedPagesCount<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token comment\">// The path to the next paginated page (or an empty string)</span>\n      nextPath<span class=\"token punctuation\">:</span> <span class=\"token function\">paginationPath</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/blog'</span><span class=\"token punctuation\">,</span> index <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> paginatedPagesCount<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>This code simply calls <code class=\"language-text\">createPage()</code> once for each paginated page. The <code class=\"language-text\">context</code> contains all the information required for that paginated page.</p>\n<h2>Page query</h2>\n<p>In the component, you use <code class=\"language-text\">skip</code> and <code class=\"language-text\">limit</code> directly inside your query. Gatsby's <code class=\"language-text\">all*</code> queries support these variables directly.</p>\n<p>For example:</p>\n<div class=\"gatsby-highlight\" data-language=\"graphql\"><pre class=\"language-graphql\"><code class=\"language-graphql\"><span class=\"token keyword\">query</span> BlogQuery<span class=\"token punctuation\">(</span><span class=\"token variable\">$skip</span><span class=\"token punctuation\">:</span> Int<span class=\"token operator\">!</span><span class=\"token punctuation\">,</span> <span class=\"token variable\">$limit</span><span class=\"token punctuation\">:</span> Int<span class=\"token operator\">!</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  allMarkdownRemark<span class=\"token punctuation\">(</span>\n    <span class=\"token attr-name\">sort</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token attr-name\">fields</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>frontmatter___date<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token attr-name\">order</span><span class=\"token punctuation\">:</span> DESC <span class=\"token punctuation\">}</span>\n    <span class=\"token attr-name\">skip</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">$skip</span>\n    <span class=\"token attr-name\">limit</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">$limit</span>\n  <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token operator\">...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2>Plugins</h2>\n<p><strong>UPDATE</strong>: We have launched our very own pagination plugin, humbly called <a href=\"https://github.com/GatsbyCentral/gatsby-awesome-pagination\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">gatsby-awesome-pagination</a>.</p>\n<p>There are two pagination plugins right now. They have very similar names! <code class=\"language-text\">gatsby-paginate</code> and <code class=\"language-text\">gatsby-pagination</code>. They both use a similar approach. You get all the data you want in <code class=\"language-text\">gatsby-node.js</code>. Then you pass that data to the component.</p>\n<p>Now your query lives in <code class=\"language-text\">gatsby-node.js</code> but your data is used in the component. Part of the magic of GraphQL is putting your queries next to your components.</p>\n<p>The packages pass data via <code class=\"language-text\">context</code>.  In the blog post example, the 10 posts per page are passed via <code class=\"language-text\">context</code>. This is not a great idea. The idea behind <code class=\"language-text\">context</code> is to pass just that, context. Not the actual data for the page. This approach somewhat abuses <code class=\"language-text\">context</code>.</p>\n<h2>Numbered links</h2>\n<p>Perhaps you want to show links like <a href=\"#\">1</a> <a href=\"#\">2</a> <a href=\"3\">3</a>. You need to create these links with custom logic. Neither pagination package provides helpers.</p>\n<p>The code to generate the links is beyond the scope of this article. In general, we recommend the following:</p>\n<ul>\n<li>Create the numbered links in <code class=\"language-text\">gatsby-node.js</code></li>\n<li>Pass the links as two arrays in <code class=\"language-text\">context</code></li>\n</ul>\n<p>This keeps the separation of concerns. All pagination logic is in <code class=\"language-text\">gatsby-node.js</code>. The component fetches all the data it requires. The component renders the previous / next / numbered links passed from <code class=\"language-text\">context</code>.</p>","excerpt":"How do you create paginated pages in Gatsby? You might have many blog posts and want to show 10 per page. Do you need a Gatsby pagination…","timeToRead":4,"frontmatter":{"date":"March 14, 2018","path":"/pagination-in-gatsby","title":"Pagination in Gatsby"}},"relatedPosts":null,"allCommentsJson":null,"allRatingsJson":{"totalCount":7,"edges":[{"node":{"id":"e8e9ba89-749f-5278-9002-7030234c3836","rating":"5"}},{"node":{"id":"8caac0f4-e3a2-54e0-8b31-c7ce672f3d3d","rating":"4"}},{"node":{"id":"d4087687-fdd4-5f0f-b421-fe0053d73b4a","rating":"1"}},{"node":{"id":"689a40aa-9fb3-54ea-84ab-e2824f4c5419","rating":"2"}},{"node":{"id":"8d595665-192d-5763-ac74-fe89fe641eb6","rating":"3"}},{"node":{"id":"7ec5ea80-7406-5fcb-9927-3e5c303b1554","rating":"3"}},{"node":{"id":"a3349a6d-1ba7-57f6-b147-c25e6e269262","rating":"1"}}]}},"pageContext":{"tags":[]}}