createPages の実装を行います。
この関数は、 Gatsby から呼ばれます。
前回作成した slug を元にページを追加します。
主な手順としては、以下になります。
編集するファイルは以下です。
./src/gatsby-helpers/createPages.ts
GraphQL を用いて Markdown コンテンツを取得します。 各 Markdown において、必要なのは slug です。 ということで、クエリ文字列は以下になります。
{
allMarkdownRemark {
edges {
node {
fields { slug } }
}
}
}
ここでハイライトされている部分が、onCreateNode で追加した部分になります。
関数の引数の型を Gatsby の型定義ファイルを参考にして以下の様に定義します。
interface CreatePagesArgs {
graphql: Function;
actions: Actions;
}
結果の値の型を GraphQL を参考にして以下の様に定義します。
interface Post {
node: {
fields: {
slug: string;
}
}
}
interface ResultType {
data: {
allMarkdownRemark: {
edges: Post[];
}
};
errors?: any;
}
createPageを呼ぶ際にページオブジェクトの以下の3つの値を指定します。
'/' で始まるページのURLを指定します。 ここで slug を使用します。
ページを構成するためのReactコンポーネントを指定します。
const blogPostTemplate = resolve('./src/templates/BlogPost.tsx');
ここファイルの説明は次回の記事にて行います。
ここで指定する値は、ページ作成の際に this.props.pageContext でアクセスできます。 また、ページクエリを使用する際のGraphQLのクエリ引数として使用できます。 例えば、context に以下の様に指定したとします。
{
foo: 'bar',
}
ページ表示用のコンポーネント側では、以下の様に呼び出すことができ $foo には 'bar' が指定されます。
export const query = graphql`
query($foo: String!) { markdownRemark(fields: { baz: { eq: $foo } }) { ...
}
}
`;
上記の例では、fields の baz が 'bar' であるページが取得されます。
実際の呼び出しは以下になります。
const posts = result.data.allMarkdownRemark.edges;
posts.map((post: Post) => {
const slug = post.node.fields.slug;
createPage({
path: `/posts${slug}`,
component: blogPostTemplate,
context: {
slug: slug,
},
});
});
ここで posts の型は Post[] であり、mapを使用して各 Post に対して createPage を呼ぶ構図になっています。
コード全体は以下の様になりました。
// ./src/gatsby-helpers/createPages.ts
import { resolve } from 'path';
import { Actions } from 'gatsby';
interface CreatePagesArgs {
graphql: Function;
actions: Actions;
}
interface Post {
node: {
fields: {
slug: string;
}
}
}
interface ResultType {
data: {
allMarkdownRemark: {
edges: Post[];
}
};
errors?: any;
}
export const createPages = ({ graphql, actions }: CreatePagesArgs): void => {
const { createPage } = actions;
return graphql(`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: ASC }
) {
edges {
node {
fields {
slug
}
}
}
}
}
`).then((result: ResultType) => {
if (result.errors) {
throw result.errors;
}
const blogPostTemplate = resolve('./src/templates/BlogPost.tsx');
const posts = result.data.allMarkdownRemark.edges;
posts.map((post: Post) => {
const slug = post.node.fields.slug;
createPage({
path: `/posts${slug}`,
component: blogPostTemplate,
context: {
slug: slug,
},
});
});
});
};
ここまでで、Markdown ファイルをページに追加する処理は完成しました。
次回は、createPage で指定した component の中身について記述します。