Reactでフォームを使ってみようシリーズも佳境に差し迫った第4弾。今回はラジオボタンを触ってみます。
時限爆弾の解体ラジオボタンComponent
もはら映画で定番となった、時限爆弾の解体シーンで「青と赤どちらのコードを切るか…」を再現するComponentを作ってみたいと思います。3色のラジオボタンが並んでおりハズレを選択(コードを切断)すると爆発します。
サンプル
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>BomButton</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <!-- Don't use this in production: --> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> </head> <body> <h1>BomButton</h1> <p>線を一つ選んで爆弾を解除してください</p> <img src="./bom1.png"> <div id="root"></div> <script type="text/babel"> class BomButton extends React.Component { constructor(props) { super(props); this.state = { radio: [ {cd:'red', name:"赤", checked:false}, {cd:'blue', name:"青", checked:false}, {cd:'green', name:"緑", checked:false} ], lastclick: null //最後に選択された色を入れる }; // State内の色の中から抽選を行う let i = Math.floor(Math.random() * 100) % this.state.radio.length; this.hit = this.state.radio[i].cd; // 爆発時の素材を事前ロードしておく this._preload(); // イベント用メソッド this.handleRadioClick = this.handleRadioClick.bind(this); } /** * 爆発時の素材を事前ロード */ _preload(){ this.se = new Audio('./bomb1.mp3'); this.se.load(); let img = new Image(); img.src = "./bakuhatsu.png"; } /** * ラジオボタンをクリック */ handleRadioClick(e) { if( ! confirm('本当にこの線で良いですか?') ){ return(false); } let name = e.target.name; let value = this.state.radio.map( (item)=>{ return({ cd: item.cd, name: item.name, checked: (item.cd===name)? true:false }) }); this.setState({ radio: value , lastclick: name }); } render() { //---------------- // 当選したら爆発 //---------------- if( this.hit === this.state.lastclick ){ this.se.play(); return <div><img src="./bakuhatsu.png" /></div> } //---------------- // 選択肢の表示 //---------------- else{ const radio = this.state.radio; const listItems = radio.map((r) => <label key={r.cd.toString()} style={{color: r.cd}}> <input type="radio" name={r.cd} value={r.cd} checked={r.checked} onChange={this.handleRadioClick} /> {r.name}<br /> </label> ); return <form>{listItems}</form> } } } ReactDOM.render( <BomButton />, document.getElementById('root') ); </script> </body> </html>
実行結果
※爆発するとSEが再生されます。音量注意。
解説
ラジオボタンの生成方法
render()
内の以下の箇所で生成していますが、基本的に前回のチェックボックスと同じですね。見た目をわかりやすくするためにCSSの指定を行っていますが、こちらは別の機会に解説したいと思います。
const listItems = radio.map((r) => <label key={r.cd.toString()} style={{color: r.cd}}> <input type="radio" name={r.cd} value={r.cd} checked={r.checked} onChange={this.handleRadioClick} /> {r.name}<br /> </label> ); return <form>{listItems}</form>
チェックボックスと異なる点としては、ラジオボタンは1つしかchecked
をtrue
にしてはならないことです。handleRadioClick()
メソッド内でState用データを作成する際の以下の箇所に注目。チェックされたname
が同じ値のときだけtrue
、異なる場合はすべてfalse
としているのがわかると思います。
let value = this.state.radio.map( (item)=>{ return({ cd: item.cd, name: item.name, checked: (item.cd===name)? true:false }) });
書籍
React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)
posted with amazlet at 18.12.24
穴井 宏幸 石井 直矢 柴田 和祈 三宮 肇
翔泳社
売り上げランキング: 139,067
翔泳社
売り上げランキング: 139,067
素材
www.irasutoya.com soundeffect-lab.info