Next.js と TypeScript で、SNSボタンを作る

TwitterFacebookHatena

TL;DR

この記事では、Next.js と TypeScript を活用し、SNS ボタンを作成する方法を紹介します。

開発環境 バージョン
Next.js 13.4.3
TypeScript 5.0.4
Emotion 11.11.0
React 18.2.0

全体のコード

次のコードは、Next.js と TypeScript、そして Emotion を利用して 2 つの SNS ボタン (Twitter、Facebook) を作成するものです。各ボタンは、指定された URL と タイトルを利用して対象の SNS でのシェア機能を持つようになっています。

// components/SnsBtn.tsx
import React from 'react'
import styled from '@emotion/styled'

const SnsButtons = styled.div`
  margin-bottom: 20px;
  display: grid;
  gap: 8px;
`

const Button = styled.a`
  display: grid;
  place-content: center;
  width: 30px;
  height: 30px;
  padding: 8px 12px;
  font-size: 14px;
  text-decoration: none;
`

const TwitterButton = styled(Button)`
  background-color: #55acee;
  color: #fff;
`

const FacebookButton = styled(Button)`
  background-color: #3b5998;
  color: #fff;
`

type Props = {
  url: string
  title: string
}

const SnsBtn = ({ url, title }: Props) => {
  const encodedUrl = encodeURIComponent(url)
  const encodedTitle = encodeURIComponent(title)

  return (
    <SnsButtons>
      <TwitterButton href={`https://twitter.com/share?url=${encodedUrl}&text=${encodedTitle}`} target="_blank" rel="noopener noreferrer">
        <img src="/icon/white/twitter-brands.svg" alt="Twitter" width="20" height="20" />
      </TwitterButton>
      <FacebookButton href={`https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`} target="_blank" rel="noopener noreferrer">
        <img src="/icon/white/facebook-brands.svg" alt="Facebook" width="20" height="20" />
      </FacebookButton>
    </SnsButtons>
  )
}

export default SnsBtn

コードの解説

それではコードを詳しく見ていきましょう。

import React from 'react'
import styled from '@emotion/styled'

まず、React と Emotion の styled 関数をインポートしています。Emotion の styled 関数は、CSS in JS を利用して React コンポーネントのスタイリングを行うことができます。

const SnsButtons = styled.div`
  margin-bottom: 20px;
  display: grid;
  gap: 8px;
`

ここでは SNS ボタンを格納するためのコンテナとなる SnsButtons コンポーネントを定義しています。grid ディスプレイが設定され、ボタン間のギャップも定められています。

const Button = styled.a`
  display: grid;
  place-content: center;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  padding: 8px 12px;
  font-size: 14px;
  text-decoration: none;
`

次に、一般的なボタンスタイルを持つ Button コンポーネントを定義しています。このスタイルは、すべての SNS ボタンで共通して適用されます。

const TwitterButton = styled(Button)`
  background-color: #55acee;
  color: #fff;
`

const FacebookButton = styled(Button)`
  background-color: #3b5998;
  color: #fff;
`

上記では、各 SNS に特有の色を背景色として設定し、テキストの色を白に設定することで、Twitter と Facebook のボタンを個別にスタイリングしています。

type Props = {
  url: string
  title: string
}

ここで、コンポーネントの Props を定義しています。これらの Props は、各 SNS のシェア機能で使用されます。

const SnsBtn = ({ url, title }: Props) => {
  const encodedUrl = encodeURIComponent(url)
  const encodedTitle = encodeURIComponent(title)
  //...
}

コンポーネント SnsBtn は、受け取った urltitle をエンコードし、それぞれを encodedUrlencodedTitle として保存します。

return (
  <SnsButtons>
    <TwitterButton href={`https://twitter.com/share?url=${encodedUrl}&text=${encodedTitle}`} target="_blank" rel="noopener noreferrer">
      <img
        src="/icon/twitter.svg"
        alt="Twitter"
        width="20

"
        height="20"
      />
    </TwitterButton>
    <FacebookButton href={`https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`} target="_blank" rel="noopener noreferrer">
      <img src="/icon/facebook.svg" alt="Facebook" width="20" height="20" />
    </FacebookButton>
  </SnsButtons>
)

return にて、エンコードされた urltitle を用いて Twitter と Facebook のボタンがレンダリングされます。これらのボタンはそれぞれの SNS のシェアリンクを持っており、ボタンをクリックすると新しいタブで該当のシェアリンクが開きます。

最後に、コンポーネントをエクスポートします。他のファイルからこのコンポーネントをインポートして使用できるようにするためのステップです。

コンポーネントを呼び出す

この SnsBtn コンポーネントを呼び出すには、以下のような形で行います。

import SnsBtn from './components/SnsBtn'

// あるコンポーネント内での利用例
function ExampleComponent() {
  const url = 'https://example.com' // シェアしたいURL
  const title = 'Example title' // シェアしたいタイトル

  return (
    <div>
      <h1>Some content here...</h1>
      <SnsBtn url={url} title={title} />
    </div>
  )
}

export default ExampleComponent

上記の例ではまず、SnsBtn コンポーネントを import 文を用いてインポートしています。次に、ExampleComponent 内で SnsBtn コンポーネントを使用しています。

SnsBtn コンポーネントは、urltitle の 2 つの props を必要とします。これらの値は、各 SNS のシェアリンクを生成するために使用されます。

url prop はシェアしたいウェブページの URL、title prop はそのページのタイトルを表しています。上記の例では 'https://example.com''Example title' をそれぞれの値として設定していますが、実際の使用では、対象となるウェブページの URL とタイトルを指定します。

このようにして SnsBtn コンポーネントを呼び出すと、指定した URL とタイトルで各 SNS にシェアするためのボタンが表示されます。ユーザーがこれらのボタンをクリックすると、新しいタブが開き、該当の SNS で指定された URL とタイトルをシェアすることができます。

環境変数を使う

記事ごとに動的なタイトルを呼び出すには、次のように環境変数を使用します。

Next.js では、[id].tsx のような動的ルーティングが利用できます。その際、ブログ記事などの特定のコンテンツを指すために、その ID を URL の一部として用いることが多いです。

以下に、Next.js の動的ページで、環境変数を使って SNS シェアボタンを実装する例を記載します。

まず、.env.local ファイル(あるいは対応する環境設定ファイル)にウェブサイトのベース URL を設定します。NEXT_PUBLIC_SITE_URL という名前で設定します。

NEXT_PUBLIC_SITE_URL=https://example.com

そして、 [id].tsx ファイルを次のように実装します。

// pages/[id].tsx
import { GetStaticProps, GetStaticPaths } from 'next'
import SnsBtn from '../components/SnsBtn'

type PostData = {
  id: string
  title: string
  // 必要に応じて他のフィールドを追加
}

type Props = {
  postData: PostData
}

const PostPage = ({ postData }: Props) => {
  const url = `${process.env.NEXT_PUBLIC_SITE_URL}/${postData.id}`

  return (
    <div>
      <h1>{postData.title}</h1>
      {/* ブログ記事の内容を表示 */}
      <SnsBtn url={url} title={postData.title} />
    </div>
  )
}

export default PostPage

export const getStaticPaths: GetStaticPaths = async () => {
  // ブログ記事のIDを全て取得し、paths を生成
  const paths = /* IDの配列を取得する処理 */
  return { paths, fallback: false }
}

export const getStaticProps: GetStaticProps = async ({ params }) => {
  // ブログ記事のデータを取得
  const postData: PostData = /* IDをもとにデータを取得する処理 */
  return { props: { postData } }
}

ここでは、動的なページの生成を行う getStaticPathsgetStaticProps を利用しています。それぞれが必要なデータの取得やパスの生成を行います。

getStaticPaths は静的生成が必要な全てのパス(この場合、全ブログ記事の ID)を返します。そして getStaticProps は、各パスに対するプロパティ(この場合、各ブログ記事のデータ)を返します。

このようにすることで、各ブログ記事ページに適切な URL とタイトルが設定された SNS シェアボタンが配置されます。

Next.js と TypeScript で、SNSボタンを作る