【2024年最新版】ほわむんボタンの作り方

こんにちは、無事デカ学院をご退院したぴくしぃです。

ところで皆さんほわむんしていますか?

おかげさまでほわむんボタンの実装から157日が経ち、約67900回も押されました!!!!!(投稿日現在)

それを記念してほわむんボタンの作り方を解説しようかな♪

ほわっ…
(ほわむんボタン工事中)

ほわむんボタン

準備

まずはAPIを作成します

そして出来たものがこちらです(ほわむん3分クッキング)

Contribute to howamun-day/howamun-api development by creating an account on GitHub.
GitHub - howamun-day/howamun-api favicon github.com
GitHub - howamun-day/howamun-api

いちいち解説するのめんどくさくなっちゃった(照)

解説しすぎても技術ブログみたいになっちゃうし

簡単に言うとdeta.spaceっていう無料でDBも使える謎のサービスを使ってほわむんボタンの押された数を保存してます

The cloud for doers and dreamers
Deta Space favicon deta.space
Deta Space

https://howamunsample-1-f1414439.deta.app/docsにAPIのドキュメントがあるので詳しく知りたい人は見てみてください

自分で作るのめんどくさかったらこれ使ってください

APIのドキュメント

裏側のAPI部分はこれで完成なので次はボタンを作りましょう!!

ブログ側のエンドポイント作成

ほわむんびよりはAstroで出来てるのでボタンを押した時に叩くエンドポイントを作成

どんな種類のデータでも提供できるエンドポイントの作成方法について学びます。
エンドポイント favicon docs.astro.build
エンドポイント

pages/api/likes.json.tsGETPUTのエンドポイントを作成

likes.json.ts
import type { APIContext, APIRoute } from "astro"
export interface Likes {
data: {
message: string
response?: {
key: string
likes: number
}
}
}
const API_URL = "デプロイしたURL" // "https://xxxx.deta.app/v1"
export const GET: APIRoute = async ({ request }: APIContext) => {
const url = new URL(request.url)
const params = new URLSearchParams(url.search)
const key = params.get("key")
if (!key) {
return new Response("missing key", { status: 400 })
}
const likes: Likes = await fetch(`${API_URL}/get/${key}`)
.then((res) => res.json())
.catch((err) => {
console.error(err)
return new Response("server fetching error", { status: 500 })
})
return new Response(JSON.stringify(likes), {
status: 200,
headers: {
"content-type": "application/json",
},
})
}
export const PUT: APIRoute = async ({ request }: APIContext) => {
const url = new URL(request.url)
const params = new URLSearchParams(url.search)
const key = params.get("key")
if (!key) {
return new Response("missing key", { status: 400 })
}
const likes: Likes = await fetch(`${API_URL}/increment/${key}`, {
method: "PUT",
})
.then((res) => res.json())
.catch((err) => {
console.error(err)
return new Response("server fetching error", { status: 500 })
})
return new Response(JSON.stringify(likes), {
status: 200,
headers: {
"content-type": "application/json",
},
})
}

API_URLの部分にはdeta.spaceでデプロイしたAPIのURLを入れてね

ボタンの作成

Astroは一部だけReactを使うとか出来るので、ボタン部分はReactで作成しクライアントのみでロードするようにする

データ取得にはSWRっていうライブラリを使います

SWRのSWRMutationとOptimistic Updatesを使って、ボタンを押したら即座に更新されるようにできるらしい すごいね

SWR is a React Hooks library for data fetching. SWR first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.
Mutation & Revalidation – SWR favicon swr.vercel.app
Mutation & Revalidation – SWR

データの取得

Howamun.tsx
const likesFetcher = (url: string) => fetch(url).then((res) => res.json())
const likesUpdater = (url: string) =>
fetch(url, {
method: "PUT",
}).then((res) => res.json())
const { data: likeCounts, error } = useSWR(
`/api/likes.json?key=${key}`,
likesFetcher,
)
const { trigger } = useSWRMutation(`/api/likes.json?key=${key}`, likesUpdater)

さっき作ったエンドポイント/api/likes.jsonkeyを渡して押された数を取得するのと、PUTで押された数を増やす

ボタン部分

Howamun.tsx
const [popupText, setPopupText] = useState<string>("")
function showRandomText() {
const texts = ["ほわっ…", "むんっ!"]
const randomText = texts[Math.floor(Math.random() * texts.length)]
setPopupText(randomText)
}

ボタンを押すたびにランダムなテキストを表示する部分

これで、ボタンを押すたびにランダムにほわっ…とかむんっ!とか表示されるようになる

Howamun.tsx
<button
onClick={() => {
showRandomText()
trigger(null, {
optimisticData: {
data: {
response: {
likes: likeCounts.data.response.likes + 1,
},
},
},
rollbackOnError: true,
})
}}
type="button"
>
{/* ほわむんボタンの見た目 */}
</button>

triggeroptimisticDataにlikesを+1増やすようにしたデータを返すことにより、ほぼリアルタイムで更新されるようにみえる お得だね

あとはボタンの見た目をいじってAstro側で

<Howamun client:load />

などとしてクライアント側だけでロードするようにしたら完成!!!!!

もっと詳しく知りたかったらキーボードのF12押してHowamun.tsxを見たらわかるらしい……


いかがでしたか?

普通にお得な情報でどうしよう

次は114514ほわむん目指して頑張るぞ~~!!!

おわりだよ~

P.S.

応用してちょうどいいボタンイキスギボタンを作りました

この記事がちょうどいいと思ったりイキスギと思ったら押してみてください