Gatsby.jsで作ったサイトでAmazonリンクを表示する
Blog
このブログはGatsby.jsで作っていますが、リンクを埋め込みカードのように表示させたいことがあります。 普通のURLはiframelyを使って表示させています。
Amazonの場合はあまりよい感じの表示にならない&アフィリエイトIDの埋め込みができないので、Amazonリンクを表示するComponentを自作しました。
<Amazon asin="B01EJ7AK5O" />
ASINコードを指定してコンポーネントを呼び出すと、こんな感じに表示されます。
<Amzn asin="B01EJ7AK5O" />
動作を確認した環境
- Gatsby.js v2.28.2
利用するAPI
商品情報の取得には、Rapid APIのAmazon Product/Reviews/Keywordsを利用しています。 アカウント登録し、あらかじめヘッダーでX-RapidAPI-Key
に指定するトークンを取得しておきます。
また、axiosを使ってAPIにリクエストを送るのでインストールしておきます。
yarn add axios
コンポーネントの作成
次の内容でcomponents/amazon.js
を作成します。 css情報は別途gatsby-browser.js
で読み込んでいるcssに記述しています。
import React, { useEffect, useState } from "react"
import axios from "axios"
import { useStaticQuery, graphql } from "gatsby"
const Amazon = props => {
const { asin } = props
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
amazon {
id
token
}
}
}
}
`
)
const { amazon } = site.siteMetadata
const [data, setData] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
axios({
method: "GET",
url:
"https://amazon-product-reviews-keywords.p.rapidapi.com/product/details",
headers: {
"content-type": "application/octet-stream",
"x-rapidapi-host": "amazon-product-reviews-keywords.p.rapidapi.com",
"x-rapidapi-key": amazon.token,
useQueryString: true,
},
params: {
country: "JP",
asin: asin,
},
}).then(resp => {
setData(resp.data)
setLoading(false)
})
}, [])
if (loading) {
return <div />
}
const { title, url, main_image, authors, description } = data?.product
return (
<div className="blog-amzn-container">
<div
className="blog-amzn-wc"
style={{ backgroundImage: `url(${main_image})` }}
></div>
<div className="blog-amzn-wt">
<div>
<strong>
<a
href={`${url}/ref=nosim?tag=${amazon.id}`}
target="_blank"
rel="noreferrer"
>
{title}
</a>
</strong>
</div>
{authors && <div>{authors[0].author}</div>}
<div>{description.replace("Read moreRead less", "")}</div>
</div>
</div>
)
}
export default Amazon
クライアントサイドでReactのマウント時にのみAPIをコールするようにします[^1](useEffect
の第2引数に空配列を指定)。
結果が返ってくるまでは(loading
がtrue
)、内容のない<div>
タグを返しておきます。結果を取得したらsetData
でstateに取得結果がセットされるので、取得結果を反映したDOM要素を返却します。
コンポーネントの定義をマッピングする
MDXファイル内でコンポーネントを毎回importするのは面倒なので、 記事を生成するテンプレート(自分の場合はblog-post.js
)に<MDXProvider>
を使ってあらかじめマッピングしておきます。
import { MDXProvider } from "@mdx-js/react"
import { MDXRenderer } from "gatsby-plugin-mdx"
...
import Amazon from "../components/amazon";
const components = { Amazon };
<MDXProvider components={components}>
<MDXRenderer>{post.body}</MDXRenderer>
</MDXProvider>