Reactでじゃんけんアプリをつくった
皆さん、じゃんけんをしたいのに、相手がいない! 困った! なんてことありませんか?
そんなお悩み解消のために、React歴2週間の経験を活かして、こんなのをつくりました。
一人でもじゃんけんができるWebサービスです。
これでいつでもじゃんけんができますね。
ソースは↓なので、ご自由にお使いください。
技術スタック
使用言語: JavaScript
ライブラリ: React
デプロイ環境: Heroku(無料)
メインロジックは147行程度です。
あとは少々CSSをいじって、レイアウトを整えました。
ざっくり解説していきます
コンポーネント設計の勘所が全然分かってないのですが、チュートリアルの知識だけでなんとなく設計しました。
命名はあんま良くないな〜と思いましたが、この規模のWebアプリならまあいいかと。
App
: 最上位コンポーネント。状態変数を管理する
Page
: ページのレンダリングを行うコンポーネント
PlayerHand
: ユーザーが出す手
OpponentHand
: 相手の手
仕様
じゃんけんアプリの仕様としては、
- プレイヤーが自分の手を選ぶまで相手の手がグーチョキパーの順で変わる
- プレイヤーが自分の手を選んだら、そのときの相手の手と勝敗を判定して、勝ち/負け/あいこを表示する
- 画面をタップすると1.に戻る
となっています。
App
のplayerHand
は初期状態では空文字が入っているので、これを利用して、
空文字だったら1.、手が入っていたら2.としてレンダリングするようにしました。
相手の手をランダムで動かすアニメーション
こだわりポイントとして、相手の手をアニメーションで動かしたいと思っていました。
「React アニメーション」でググると、追加でライブラリ入れろとか、CSSアニメーションを使えとか、色々出てきて混乱しましたが、
よくよく考えてみると、タイマー処理で状態変数を一定間隔で変更すれば、
そのたびにReactはレンダリングが走るので、アニメーションっぽく画面が更新できることに気づきました。
setTimer() {
this.timerID = setInterval(
() => this.changeOpponentHand(),
500
);
}
changeOpponentHand() {
if (this.state.playerHand) { return; }
if (this.state.opponentHand === "✊") {
this.setState({
opponentHand: "✌️"
});
} else if (this.state.opponentHand === "✌️") {
this.setState({
opponentHand: "✋"
});
} else if (this.state.opponentHand === "✋") {
this.setState({
opponentHand: "✊"
});
}
}
もうちょっと頭使ったら、条件分岐をすっきり書けそうな気もしますが、愚直に書きました。
コンポーネント分割でハマった
基本的には割とサクサク進んだ開発でしたが、一個だけハマったのが、
propsで親コンポーネントから子コンポーネントにメソッド渡したときに、思ったように動かなくて半日ぐらいとられました。
元々親コンポーネントでsetPlayerHand(hand)
という処理をやっていて、動くのを確認してから、
一回じゃんけんで勝負がついた後のリセットを入れたいので、Page
という子コンポーネントをつくって、
const page = <Page
playerHand={playerHand}
opponentHand={opponentHand}
onClick={(hand) => this.setPlayerHand(hand)}
/>
if(playerHand) {
return (
<div className="app" onClick={this.startNewGame}>
{page}
</div>
);
} else {
return (
<div className="app">
{page}
</div>
);
}
という感じで分岐しています。
ここも本当は三項演算子使って、
<div className="app" onClick= { playerHand ? this.startNewGame : null }>
みたいな書き方がしたいんですが、できなかったので、こんな書き方になっています。
最初、App
→Page
に対して、
onClick={() => this.setPlayerHand}
でメソッドを渡していて、これで渡すと子コンポーネントから引数指定しても、SyntheticEvent
が渡されるという謎の挙動になりました。
全然わからなかったので、もはやイベント変数経由で値渡せないかとか調べましたが、それはそれで挫折しました。
で、
onClick={(hand) => this.setPlayerHand(hand)}
この書き方だと、正しく引数が渡せました。
この辺のアロー関数の理解がそもそも甘いので、本格的にWeb開発やるならまずJSの基本(ES6)からやりたいですね。
Reactはなんかテンション上がる
このじゃんけんアプリは当初Ruby on Railsでつくろうと思っていたネタなんですが、結局Railsでは開発しませんでした。
RailsはRailsで全然整理されたフレームワークだと感じましたが、なんかテンションが上がる感じはなかったです。
Reactは触ってるとなんかテンションが上がる感じがありました。
なんでしょうね。
「このリッチな表現がこれだけのコードでできたよオイ」みたいな感覚があるんですよね。
もちろん宣言的UI特有の大変さはあるので、とっつきやすさは圧倒的にRailsに軍配が上がるんですが、
Reactはとっつきづらい分、その見返りがしっかりある感じがして、体感がよかったです。
流行ってるフレームワークだから、というのもあるんでしょうけど、
それ以上に流行る理由としての合理性・必然性みたいなところが感じられました。
今後
とりあえずReactそのものは完全に理解できたので、今度はもうちょっと本格的なものをつくりたい気持ちがあります。
自分のWebサイト(ポートフォリオ+個人ブログみたいなイメージ)をつくるのを妄想しています。
中身全然わかりませんが、Next.jsとVercelを使うと良さそうなので、つくってみたいです。
本格的に開発するなら、型チェックがないしんどさがだいぶあったので、TypeScriptの導入もしたいです。
Webフロントももっとやりたいですが、個人開発用のデプロイ環境ももっと良くしたい気持ちもあります。
HerokuはHerokuでお手軽で素晴らしいんですが、やはり無料アカウント故の限界もあるので、デプロイ環境をもうちょい調べたい気持ちがあります。
来週のテーマ
ゴニョゴニョWeb技術の野望を書きましたが、来週はFlutterをやりたい思ってます。
Flutterも名前しか知らないので、まずは何をやったらいいかを調べるところからのスタートですね。
Discussion