Create a Table of Contents Component for MDX Documents in Gatsby

John Otander
InstructorJohn Otander

Share this video with your friends

Send Tweet
Published 3 years ago
Updated a year ago

When you use a component for your table of contents in MDX documents you have more flexibility around how you render it. In this lesson, we'll use Gatsby's GraphQL data layer to fetch the headings in an MDX document and pass them to a TableOfContents component that we create.

Instructor: [00:00] With a functioning Gatsby and MDX site, we can first open up GraphiQL. You can click on the Explorer, find all MDX nodes, and then grab the headings, depth, and value. GraphiQL will automatically create the query for us. When we execute, we can see the data that we'll use to construct our table of contents.

[00:27] Now we can open up our page and modify our page query. Currently, we're only querying for the MDX body. This is where we can also add in the headings, depth, and value. With that data now being queried, we'll need to pass it along to our MDX renderer.

[00:45] Gatsby plugin MDX will automatically pass these props to our MDX document. We can use a pretag in the JSON stringify to log them out. When we inspect our headings, we can see that there's no id for us to link to in our table of contents.

[01:00] To achieve this, we can install the remark-slug plugin, then pass it to gatsby-plugin-mdx as part of the remarkPlugins array. We can restart Gatsby develop and inspect our heading to see the slugified ID. Now we're ready to start our table of contents component.

[01:19] As our first pass, we can log the headings in a pretag like we did in the MDX document. Back in our MDX document, we can import the table of contents, and then render it passing it the headings from props.

[01:34] Now we can go back to our table of contents component and begin an unordered list. We'll map over the headings, pass the heading.value as the key, and then render the heading.value.

[01:47] We need to create the slug in our component so we know what to link to. We can use Github slugger for that. Once the library is installed, we can import github-slugger, instantiate it, and then render it next to our heading.value.

[02:02] To construct our link, we can import it from Gatsby, and then pass it our slug, prefixed by the pound sign. Though it looks weird that our h1 is part of our table of contents. We can filter that out with the depth. Now, it looks good.

[02:18] All together, we've created a table of contents component that uses Github slugger and Gatsby link, filters out headings of depth 1, and then renders them as list items. In our page component, we've updated the query to include the headings, depth, and value, and then passed that as a property to MDX renderer.

[02:36] Lastly, in our MDX document, we've imported the component, and then rendered it passing the props.headings.