オリジナルの記事はこちら
こんにちは。mono(@mono7555e)です。
記事ページで他の記事へ行く術がなく直帰率が高くなっていたので他の記事への遷移を追加することにしました。
ちょっとひと手間かかりますがGatsbyJSでも実現できましたのでご紹介したいと思います。
exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions
const template = path.resolve(`src/templates/blog.tsx`)
await graphql(`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___published_at] }
limit: 2000
) {
edges {
node {
fields {
slug
}
frontmatter {
title
image
}
}
}
}
}
`).then(result => {
if (result.errors) {
return Promise.reject(result.errors)
}
const pages = result.data.allMarkdownRemark.edges
pages.forEach(({ node }, index) => {
const prev = index === 0 ? null : pages[index - 1].node
const next = index === pages.length - 1 ? null : pages[index + 1].node
createPage({
path: node.fields.slug,
component: template,
context: {
slug: node.fields.slug,
prev,
next,
},
})
})
})
}
重要なのはconst prev = ~
とconst next ~
の部分と、contextでそれを設定している部分です。
それ以外のところは自由です。
ちょっとごちゃごちゃしてしまったので前後の記事用のコンポーネントに分割しました。
import React from "react"
import { Box, Card, CardActionArea, CardContent, Typography } from "@material-ui/core"
import Image from "../atoms/image"
const PrevNext = ({ prev, next }) => {
return(
<Box mt={5} display="flex" justifyContent="space-between">
{ prev == null ? null : _link(prev, `prev`)}
{ next == null ? null : _link(next, `next`)}
</Box>
)
}
export default PrevNext
const _link = ({ fields, frontmatter }, direction) =>{
return(
<Box display="flex" flexDirection="column" style={{ width: `40%` }}>
<Typography gutterBottom variant="body2" component="h6">
{ direction == 'prev' ? '前の記事' : '次の記事'}
</Typography>
<Card style={{ width: `100%`, height: `100%`}}>
<CardActionArea href={fields.slug} style={{ display: 'flex', alignItems: `stretch`, height: `100%` }}>
<Box style={{ width: `35%` }}>
<Image filename={frontmatter.image} style={{ height: `100%` }} />
</Box>
<CardContent style={{ flex: `1` }}>
<Typography variant="body2" component="p">
{frontmatter.title}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Box>
)
}
このブログはMaterial-UIを使っているのでちょっとややこしい感じになりますが、単純にリンクをするだけであればもう少し簡単に書けると思います。
あとは作った前後の記事用のコンポーネントをテンプレートから呼び出すだけです。
// importなどなど
export default function Template({ data, pageContext }) {
// 中略
return (
<Layout>
<Container maxWidth="md" component="article">
{/* その他コンポーネント読み込み */}
<PrevNext prev={pageContext.prev} next={pageContext.next} />
</Container>
</Layout>
)
}
やってみると結構かんたんでした。
今はイメージとタイトルだけですが、タグや日付など各記事が持っている情報を利用できるのでよりリッチな前後の記事へのリンクが設置できると思います。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント