Skip to main content

Implementing Share Buttons in Docusaurus: A Log and Troubleshooting Guide

· 5 min read
hiroaki
Individual Developer

Implementing the Share Buttons

I've added share buttons to each article on this site for social media sharing. This post documents the implementation process and the technical decisions behind it.

A key feature of the final component is its ability to automatically fetch the page title and URL. This means that once it's set up, there's no need for special configurations on a per-article basis, which minimizes maintenance.

Choosing the Implementation Strategy

Docusaurus has a powerful feature called swizzle that allows you to directly override core theme components. However, I chose not to use this feature for this implementation.

The reason is that swizzle tightly couples the project to a specific Docusaurus version, increasing the risk of compatibility issues during future upgrades. To prioritize long-term stability and maintainability, I opted for an approach that doesn't rely on swizzle, implementing it as an independent React component. This ensures a robust structure that is less susceptible to breaking changes from Docusaurus core updates.

The Implementation Process

First, I added the react-share library, which provides the share button functionality, to the project.

pnpm add react-share

Next, I created a component to encapsulate the share button logic and UI at src/components/ShareButtons/index.tsx. There are a few key points to this implementation.

The first point is handling an issue with the library's type definitions. The React 19 environment used in this project is not yet fully supported by react-share, which would cause TypeScript type errors. To safely work around this while limiting the scope of the fix, I intentionally bypassed the type check using as any.

// src/components/ShareButtons/index.tsx

import {
TwitterShareButton as OriginalTwitterShareButton,
// ... other buttons imported similarly
} from 'react-share';

// To safely work around the library's type definitions not being compatible with React 19
const TwitterShareButton = OriginalTwitterShareButton as any;
const FacebookShareButton = OriginalFacebookShareButton as any;
// ...

The second point is the core of this component: dynamically fetching page information. Inside a useEffect hook, the page title is extracted from the browser's document.title. Docusaurus generates page titles in the format Article Name | Site Name, so I use string manipulation to remove the site name part and get the pure article title.

// src/components/ShareButtons/index.tsx

useEffect(() => {
// Generate the full URL of the current page
setPageUrl(new URL(location.pathname, siteConfig.url).href);

let title = '';
if (typeof document !== 'undefined') {
// Remove the site name part from the `document.title` generated by Docusaurus
const siteTitleSuffix = ` | ${siteConfig.title}`;
title = document.title.endsWith(siteTitleSuffix)
? document.title.slice(0, -siteTitleSuffix.length)
: document.title;
}
setPageTitle(title);

// ...
}, [/* ...dependency array... */]);

For styling, I used CSS Modules (styles.module.css) to encapsulate the component's styles. This allows me to define the button's layout and hover effects without affecting other parts of the site.

How to Use the Component

Finally, the completed component is placed in an article file (.mdx). It's very simple to use—just import the file and call the component.

...end of the article body...

---

import ShareButtons from '@site/src/components/ShareButtons';

<ShareButtons />

By adding these few lines, I can easily add sharing functionality to any article. Implementing it without swizzle enhances resilience against Docusaurus version upgrades, and by applying a targeted fix for the library's type issues, I've created a maintainable, reusable, and self-contained component.


Troubleshooting: Resolving Library Type Errors in a React 19 Environment

In modern front-end development, it's common to face unexpected errors during the transition period while libraries catch up with framework evolutions. This is a record of how I addressed multiple TypeScript errors that occurred when introducing the react-share library into a React 19 and Docusaurus v3 environment.

The Problem I Encountered

As I proceeded with the implementation, the compiler reported several puzzling errors. For example, an error stating that the children property was missing, and another that the JSX namespace did not exist. Furthermore, for the Facebook share button, the quote property, which is recommended in the official documentation, was flagged as not existing in the type definition.

These errors suggested that the problem wasn't with my code's logic but stemmed from a deeper, underlying cause.

Root Cause Analysis

After investigation, I found that the errors could be attributed to two main causes.

First was version incompatibility between the library and the framework. react-share had not yet fully adapted to the new type definitions changed in React 19, particularly how the children property is handled.

Second was a flaw in the library's own type definition files. The fact that the quote property for FacebookShareButton was not described in the type definition file was a clear bug on the library's side.

These issues did not originate from my application code but from the library I was depending on. Therefore, the solution was not to wait for a library fix but to safely 'work around' the problem in my own code.

A Solution with Limited Scope

The easiest way out in such a situation is to silence the error with a // @ts-ignore comment, but this is not the best approach as it can become a breeding ground for future bugs and significantly reduces code readability.

The approach I adopted was safe type casting with a limited scope. I intentionally relaxed the type for only the problematic components using as any and redefined them as new components.

// Import the original component with an alias
import {
TwitterShareButton as OriginalTwitterShareButton
} from 'react-share';

// Perform type casting to define the component for use within the application.
// This contains the type error within this file.
const TwitterShareButton = OriginalTwitterShareButton as any;

The advantage of this method is that it limits the scope of disabling type checking to only the problematic parts. Anyone reading the code can clearly understand why the type casting is being done, and when the library is updated in the future, it's easy to revert to the original type-safe state by simply removing these few lines.