Reactに挑戦してみる 8
概要
Reactに挑戦してみる8。ここから少し複雑になりそう。
参考書籍
WebデベロッパーのためのReact開発入門 JavaScript UIライブラリの基本と活用
- 作者: 柴田文彦
- 出版社/メーカー: インプレス
- 発売日: 2016/11/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
Reactで使うフォーム~HTMLとの比較
Reactは、条件に応じて、表示させる項目を変えたりする時に便利。
form.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Text Input Example</title> <script src="http://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> </head> <body> <div>HTML Input: <input type="text" value="入力欄" /></div> <div id="content"></div> <script type="text/babel" src="textinput.js"></script> </body> </html>
textinput.js
var TextInput = React.createClass({ render: function(){ return (<div>JSX input: <input type='text' value='入力欄' /></div>); } }); ReactDOM.render( <TextInput />, document.getElementById('content') );
これで、htmlとjsxのフォームを比較してみる。
- jsxのほうは、編集ができない。value=で指定したものは、valueを更新しない限り編集ができないらしい。JSXで、htmlのvalue(初期値)のようにしたい場合は、defaultValueを使うらしい。
- ただ、valueを指定していないinput要素はデータの受け渡しができないので意味がない。
- こういう時は、コンソールのerrorを見てみるといいらしい。
Failed form propType: You provided a
valueprop to a form field without an
onChangehandler.
とのことなので、編集した時の処理ように、onChangeを使うといいらしい。
var TextInput = React.createClass({ # Stateを設定する。ここでは、dispTextというstateの初期値を設定している。 getInitialState: function(){ return {dispText: '入力欄'}; }, # handleInputは独自のメソッド。JSXのinputが変更された時に呼び出される。this.setStateメソッドで、event.target.valueをdispText stateに代入するように設定してある。 handleInput: function(event){ this.setState({dispText: event.target.value}); console.log(this.state.dispText); }, # value=dispTextで、onChangeした時に、handleInputが呼び出されるようになっている。 render: function(){ return (<div>JSX InputText: <input type='text' value={this.state.dispText} onChange={this.handleInput} /> </div>); } }); ReactDOM.render( <TextInput />, document.getElementById('content') );
ちょっとずつ難しくなってきたな。
type属性とchecked属性でラジオボタンを実現する
var RadioButton = React.createClass({ render: function() { return (<div>どれか1つを選んでください。: <div> <input type="radio" name="三択" value="first" checked />最初の選択肢 </div> <div> <input type="radio" name="三択" value="second" />次の選択肢 </div> <div> <input type="radio" name="三択" value="third" />最後の選択肢 </div> </div>); } }); ReactDOM.render( <RadioButton />, document.getElementById('content') )
これだと、onChangeがなくて編集ができないので、テキストボックスの時と同じように修正する。
var RadioButton = React.createClass({ # selectionというStateの初期値をセットする。 getInitialState: function(){ return {selection: 'first'}; }, # onChangeで呼び出されるメソッドをセットする。Stateを変更するという内容。 handleChange: function(event){ console.log(event.target.value); this.setState({selection: event.target.value}); }, # renderメソッドをセットする。checkedの属性に、合致するvalueの時だけcheckedがつくようにセットする。 render: function() { return (<div>どれか1つを選んでください。: <div> <input type="radio" value="first" checked={this.state.selection ==='first'} onChange={this.handleChange} />最初の選択肢 </div> <div> <input type="radio" value="second" checked={this.state.selection ==='second'} onChange={this.handleChange} />次の選択肢 </div> <div> <input type="radio" value="third" checked={this.state.selection ==='third'} onChange={this.handleChange} />最後の選択肢 </div> </div>); } }); ReactDOM.render( <RadioButton />, document.getElementById('content') )
type属性で複数選択可能なチェックボックスを作成する。
var CheckBox = React.createClass({ # Stateの初期値を配列でセットする。 getInitialState: function(){ return {selection: ['first']}; }, # selection stateのコピーを作成する # valueのselection state内の配列での位置をpositionに代入する。 handleChange: function(event){ var selection = this.state.selection var position = selection.indexOf(event.target.value); # onChangeされた時に、対象がチェックされていたら、そのvalueをselection state配列にpushする。 if (event.target.checked){ selection.push(event.target.value); # それ以外の時(チェックが外された場合)は、spliceで、要素を削除する。 } else { selection.splice(position, 1); } # 上記の処理をした後に、再度selectionをstateにセットする。 this.setState({selection: selection}); console.log(event.target.value); }, # render メソッドをセットする。 render: function() { return (<div>複数回答可です。: <div> <input type="checkbox" value="first" # indexOfは、含まれている場合は、positionの位置を返して、含まれてない場合は、-1を返すのか? checked={this.state.selection.indexOf('first') !== -1} onChange={this.handleChange} />最初の選択肢 </div> <div> <input type="checkbox" value="second" checked={this.state.selection.indexOf('second') !== -1} onChange={this.handleChange} />次の選択肢 </div> <div> <input type="checkbox" value="third" checked={this.state.selection.indexOf('third') !== -1} onChange={this.handleChange} />最後の選択肢 </div> </div>); } }); # 上記でセットした(上書きした?)renderメソッドで、html要素を返す。 ReactDOM.render( <CheckBox />, document.getElementById('content') )
うーん、ちょっと冗長な感じがするなぁ、まあたぶんフォームを直接reactで作ることはないと思うからいいか(^ ^;)
プロパティによって選択状態の初期値を設定する
var CheckBox = React.createClass({ getInitialState: function(){ // ここで、props.selectionを初期値に代入する return {selection: this.props.selection}; }, // 中略 ReactDOM.render( // ここで、propsの初期値をセットする。 <CheckBox selection={['second','third']} />, document.getElementById('content') )
value属性でセレクトボックスを選択可能にする。
1つだけ選択する場合
var SingleSelection = React.createClass({ # Stateの初期化を、プロパティを代入してセットする。 getInitialState: function(){ return {selection: this.props.selection}; }, # changeした時に呼び出すメソッドを設定 handleChange: function(event){ console.log(event.target.value); this.setState({selection: event.target.value}); }, # render時のメソッドを設定 render: function() { return (<div>どれか1つを選んでください。: <select onChange={this.handleChange} multiple={false} value={this.state.selection}> <option value="first">最初の選択肢</option> <option value="second">次の選択肢</option> <option value="third">最後の選択肢</option> </select> </div>); } }); # renderメソッドで、html要素を返す ReactDOM.render( <SingleSelection selection={'third'} />, document.getElementById('content') )
複数選択可能にする場合
var SingleSelection = React.createClass({ # Stateの初期化メソッド、初期値には、プロパティ値をセットする。 getInitialState: function(){ return {selection: this.props.selection}; }, # onChangeの時によびだされるメソッドの設定 handleChange: function(event){ # selectionに、selection stateを代入してコピーを作成する、対象のpositionもゲットしておく。 var selection = this.state.selection; var position = selection.indexOf(event.target.value); if (position === -1) { selection.push(event.target.value); }else{ selection.splice(position, 1); } this.setState({selection: selection}); console.log(event.target.value); }, # renderメソッドをセットする。 render: function() { return (<div>複数回答可能です。: <select onChange={this.handleChange} multiple={true} value={this.state.selection} size="3"> <option value="first">最初の選択肢</option> <option value="second">次の選択肢</option> <option value="third">最後の選択肢</option> </select> </div>); } }); # カスタムコンポーネントをrenderメソッドで、html要素として返す。 ReactDOM.render( <SingleSelection selection={['first','third']} />, document.getElementById('content') )