こんにちは、無事デカ学院をご退院したぴくしぃです。
ところで皆さんほわむんしていますか?
おかげさまでほわむんボタンの実装から157日が経ち、約67900回も押されました!!!!!(投稿日現在)
それを記念してほわむんボタンの作り方を解説しようかな♪
ほわむんボタン
準備
まずはAPIを作成します
そして出来たものがこちらです(ほわむん3分クッキング)
いちいち解説するのめんどくさくなっちゃった(照)
解説しすぎても技術ブログみたいになっちゃうし
簡単に言うとdeta.spaceっていう無料でDBも使える謎のサービスを使ってほわむんボタンの押された数を保存してます
![Deta Space](https://deta.space/landing-page/static/social-preview.png)
https://howamunsample-1-f1414439.deta.app/docs
にAPIのドキュメントがあるので詳しく知りたい人は見てみてください
自分で作るのめんどくさかったらこれ使ってください
裏側のAPI部分はこれで完成なので次はボタンを作りましょう!!
ブログ側のエンドポイント作成
ほわむんびよりはAstroで出来てるのでボタンを押した時に叩くエンドポイントを作成
![エンドポイント](https://docs.astro.build/open-graph/ja/guides/endpoints.png)
pages/api/likes.json.ts
にGET
とPUT
のエンドポイントを作成
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を使って、ボタンを押したら即座に更新されるようにできるらしい すごいね
データの取得
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.json
にkey
を渡して押された数を取得するのと、PUT
で押された数を増やす
ボタン部分
const [popupText, setPopupText] = useState<string>("")
function showRandomText() {
const texts = ["ほわっ…", "むんっ!"]
const randomText = texts[Math.floor(Math.random() * texts.length)]
setPopupText(randomText)
}
ボタンを押すたびにランダムなテキストを表示する部分
これで、ボタンを押すたびにランダムにほわっ…とかむんっ!とか表示されるようになる
<button
onClick={() => {
showRandomText()
trigger(null, {
optimisticData: {
data: {
response: {
likes: likeCounts.data.response.likes + 1,
},
},
},
rollbackOnError: true,
})
}}
type="button"
>
{/* ほわむんボタンの見た目 */}
</button>
trigger
のoptimisticData
にlikesを+1増やすようにしたデータを返すことにより、ほぼリアルタイムで更新されるようにみえる お得だね
あとはボタンの見た目をいじってAstro側で
<Howamun client:load />
などとしてクライアント側だけでロードするようにしたら完成!!!!!
もっと詳しく知りたかったらキーボードのF12押してHowamun.tsx
を見たらわかるらしい……
いかがでしたか?
普通にお得な情報でどうしよう
次は114514ほわむん目指して頑張るぞ~~!!!
おわりだよ~
P.S.
応用してちょうどいいボタンとイキスギボタンを作りました
この記事がちょうどいいと思ったりイキスギと思ったら押してみてください