Reactガイドを読んでいくその12
これは
Reactのガイドを読んでいく記事です。
ガイドのリンク
フォーム
フォーム2日目。
textarea タグ
HTMLでのtextareaは以下のように子要素にテキストを持つ。
<textarea> Hello there, this is some text in a text area </textarea>
ReactではValueを指定する
class EssayForm extends React.Component { constructor(props) { super(props); // ここ this.state = { value: 'Please write an essay about your favorite DOM element.' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); }
select タグ
HTMLの場合selectタグはドロップダウンリストを作る。
<select> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option selected value="coconut">Coconut</option> <option value="mango">Mango</option> </select>
Reactではちょっと複雑になっていますが、やりたいことは同じ。
valueを使う仕組みなのは他と変わらず。
class FlavorForm extends React.Component { constructor(props) { super(props); this.state = {value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Pick your favorite flavor: <select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </label> <input type="submit" value="Submit" /> </form> ); } }
file input タグ
HTMLでは、<input type="file">
でユーザーにファイルを選択させる機能がある。
Reactではこれは非制御コンポーネントになり、ここでは割愛されている。
複数の入力の処理
複数の入力をしたい場合は、それぞれにnameを用意することで解決することが可能。
class Reservation extends React.Component { constructor(props) { super(props); this.state = { isGoing: true, numberOfGuests: 2 }; this.handleInputChange = this.handleInputChange.bind(this); } handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }); } render() { return ( <form> <label> Is going: <input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange} /> </label> <br /> <label> Number of guests: <input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange} /> </label> </form> ); } }
制御された入力における null 値
制御されたコンポーネントで value プロパティに値を指定することで、変更させたくない場合にユーザーが値を変更できないようになる。
設定しているにも関わらず、変更できてしまうような場合はundefinedやnullが設定されてしまっていることが原因。
ReactDOM.render(<input value="hi" />, mountNode); // しばらくすると編集可能になる setTimeout(function() { ReactDOM.render(<input value={null} />, mountNode); }, 1000);
制御されたコンポーネントの代替手段
制御されたコンポーネントは、あらゆる種類のデータの変更に対してイベントハンドラを書き、あらゆる入力状態を React コンポーネントに通してやる必要があるため、時としてうんざりすることがあります。
確かに。
既存のものをReactに変換していくのとかすごく苦労しそう。
そういう場合は非制御コンポーネントを使えってことらしい。
ADVANCEの内容なので随分先になりそうだけど覚えておこう。
ja.reactjs.org
本格的なソリューション
Formikを使うと便利らしい。
Redux-Formより優れている点がまとめられている。 qiita.com
Redux-Formよくわからないのでそっちはそっちで知らないと良し悪しがよくわからなかった。
今日はここまで。
Reactガイドを読んでいくその11
これは
Reactのガイドを読んでいく記事です。
ガイドのリンク
フォーム
今回は何回かに分けます。
フォームをイメージするのに時間がかかってしまった...。
HTMLHTMLフォームが持つ状態があるためReactは他のDOMとは違う動作をする。
基本的にはHTMLが持つデフォルトのフォームの動きをするが、ユーザの入力などに対して入力データに直接アクセスするようなJavaScriptがあったほうが便利。
制御コンポーネントと呼ばれるテクニックでこれを実現可能にする。
制御されたコンポーネント
HTMLにおける 、
Reactではstateを唯一の情報源とすることで単独で入力データを保持し、直接アクセスするようにすることができる。Reactによって制御される入力フォームは「制御されたコンポーネント」と呼ぶ。
下はフォーム送信時に名前をログに残すような処理になる。
class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; //ここ this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } // ここ handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: // ここ <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }
今日はここまで。
【緊急来日】Nreal Developer Gathering【増枠】に参加してきた
これは
2019/10/08(火)に行われた【緊急来日】Nreal Developer Gathering【増枠】に参加した時のメモと感想記事です。
イベントページ
会場:IGNITIONPOINT様
ハッシュタグ:#NrealDev
講演内容(※敬称略)
主催挨拶&諸連絡 (19:25 ~ 19:30)
会場のお話と会場提供のIGNITIONPOINT様からのお話。
会場の名前は「SPARK2045」というのだけれど、2045の理由はシンギュラリティから。
NrealLight & NRSDK紹介プレゼンテーション (19:30 ~ 20:15)
講演内容:
nrealの紹介とこれから
メモ:
・SFの世界で見るようなメガネ型のデバイスを実現させたく頑張ってきた
・3年前に設立してから今では120名の社員がいる
・CESで発表し、次のCESまでに開発者向けの充実を図り、その次はコンシューマー向けに展開していく
・ハンドジェスチャ機能は今後対応していきたい
・開発者12.7%が日本に。中国より多い。一番はアメリカ
・当初から日本には注力していたが、SDKダウンロード数が伸びているので今後も日本は注力していく
・年内に日本むけtechdayをしたいのでお楽しみに
講演時に自分が参照したリンクたち
感想
日本の開発者そんなにいるの?ってくらい多かったのでびっくりした。
日本向けに注力していくという姿勢はリップサービスでなく、日本支社(最近スタートアップ熱の高い大手町にあるらしい)の展開や
KDDIとの連携などからも伺える。
デザイン性がよくサングラスとの置き換えを考えると非常に良さげ。屋外でどこまでその存在を確認できるかは期待したい。
メガネ側にマイクもスピーカーもあるので非常に完成度が高い印象を受けた。
パネルディスカッション (20:15 ~ 21:00)
講演内容:
パネラーから見たnrealの現状とこれから期待すること
資料:
なし
メモ:
・CESではHoloを抑えてNrealはすごかった
・nrealの登場によって眼鏡をかける未来が想像できるようになった
・ライフスタイルに溶けたデザインこそが普及と言えると考えているのでnrealは理想に近い
・SDKを使った開発はSDKとして担って欲しい機能に不足があるものの非常に使いやすい
・1日中装着できるようになったら世界が本当に変わる
・現状では熱やバッテリー問題で装着し続けるのは難しい
・歩きスマホ問題を解決するかもしれないと期待したが、情報がそこにある以上歩きスマホは危険
・アパレルの形がデバイスの進化で変わってくるというのが期待としてある
・nrealの機能としてはシェアリングが欲しい
・メガネ型のデバイスにはライフログに期待
感想
生活に溶けていくというのはいいなと思った。
ライフログについてはゆくゆくプライバシー問題でNGになる方針が出るだろうけど、やれるかどうかやって見たいなという気持ちはわかる。
特に視界として捉えているけど意識できていない部分を後追いでもピックアップできるようになるのは人間の拡張として便利だなと思う。
従来の看板が街から消えてARむけになると景色もまた変わってきたりするんじゃないかなーと期待。
今のQRと同じくらい普及した時がその時かな。
体験の感想
良くも悪くも「スマホ手元じゃなくてメガネに映して欲しいわ。ARとか不便なんだよ」を実現したデバイスと言える。
ちらつきもなく、視野角もしっかり広いのでストレスがない。
そして何より軽い。ただ、それはデバイスをかけるのを比較してなので、サングラスと置き換えた場合微妙な印象を受けるかもしれない。
AndroidNativeAppが使えるのは非常に魅力的だけれど、スマホが別途必要で結構スペックが高いものを要求されるのでnrealの価格自体は安いもののトータルで見ると高くなってしまうのでは?という懸念もある。
上でも書いたようにスマホがメガネになったが近いのでスマホのオプションと考えれば想像できそうなところ。
スナドラ845のデバイスコントローラ付きの方は面白い形をしていて、キュート。
ちょっとわかりにくいけど奥で持ってる白い丸いのがコントローラーになるので小さくて使いやすい。
マグネットで大きい四角のにくっついている。
メガネを装着してさらにnrealをつけることができないのでちゃんと公式レンズがあった。
MLでもあったけど、こういうのは必要になってくるよなと思う。
体験できなかった6DoFコントローラは専用機ではなく、これらしい。
体験者から聞いたお話だとずれるし、体験的には微妙とのこと。
ちなみに公式orスマホでは3DoFになる。
www.moguravr.com
メガネ側とコントローラ側にそれなりに熱を持つので、やはり装着し続けるのは難しいかなと思う。
排熱処理はよくなっていくのだろうか。
スピーカーがついている話だったけど、開発者版はなかったのかな?音が聞き取りにくかった。
もしかすると会場の熱気で聞き取りにくいだけだったのかもしれない。
常に改良が加えられている状況のようなので、nrealコンシューマー版が出るときを楽しみにしていたい。
Reactガイドを読んでいくその10
これは
Reactのガイドを読んでいく記事です。
ガイドのリンク
リストと key
JavaScriptではmap()を使ってリスト変換をします。
const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((number) => number * 2); console.log(doubled); // [2,4,6,8,10]
Reactもほぼ同様の機能を持っています。
Reactは中括弧で囲むことで実現することが可能です。
const numbers = [1, 2, 3, 4, 5]; // JavaScriptとは書き方が異なる点注意 // ここだけ考えるとJavaScriptの方が簡単に見える。 const listItems = numbers.map((number) => <li>{number}</li> ); ReactDOM.render( // DOMへ上で行ったlistitemを出力するようにしている <ul>{listItems}</ul>, document.getElementById('root') ); /* ・1 ・2 ・3 ・4 ・5 */
基本的なリストコンポーネント
コンポーネント内部でレンダリングしたい場合リスト項目にはkeyが必要となります。
実行はするもののワーニングを出すので、対応しておくべき項目になります。
"Warning: Each child in a list should have a unique 'key' prop.%s%s See https://fb.me/react-warning-keys for more information.%s" " Check the top-level render call using <ul>." "" " in li"
チュートリアルをやっているときにやった内容ですね。
Key
KeyはReactがどの要素が変更・追加・削除されたのかを識別するのに役立ち、
それぞれ一意にIDが振られることでReactが少ない処理で動くことができるようになります。
IDを触れない場合はインデックスという形で処理をすることが可能ですが、処理速度は遅くなるので忌避される。
key のあるコンポーネントの抽出
map()の呼び出しのなかに登場する要素にkeyをつけるという考え方が基本となります。
なので、以下のような場合は不適切。
function ListItem(props) { const value = props.value; return ( // Wrong! There is no need to specify the key here: <li key={value.toString()}> {value} </li> ); }
正解はこちらになります。
function ListItem(props) { // Correct! There is no need to specify the key here: return <li>{props.value}</li>; } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Correct! Key should be specified inside the array. <ListItem key={number.toString()} value={number} /> ); return ( <ul> {listItems} </ul> ); }
なのでkey が意味を持つのは、それをとり囲んでいる配列の側の文脈となります。
key は兄弟要素の中で一意であればよい
keyそのものは全体で一意である必要はないが、配列内では一意である必要があります。
配列一つ一つが独立したDBと考えれば、当然と言えば当然と言えます。
keyはReact側に必要な情報であって、コンポーネントとしては不要で、渡されることのない情報になります。
map() を JSX に埋め込む
JSXでは任意の式の埋め込みが可能なので、map()も埋め込みが可能。
スッキリして見えるのでよく使われる方法だが、コード規約に則り多用は考えて使うことが求められる。
Before
function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <ListItem key={number.toString()} value={number} /> ); return ( <ul> {listItems} </ul> ); }
After
function NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul> ); }
今日はここまで。
Reactガイドを読んでいくその9
これは
Reactのガイドを読んでいく記事です。
ガイドのリンク
条件付きレンダー
ReactのレンダーはJavaScriptの条件分岐のように条件付きでレンダー範囲を指定することができる。
以下のコードはGreetingファンクションの中でログイン状態によって表示する文字を変更するようになっている。
※isLoggedInが条件のパラメータを持つ
function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } ReactDOM.render( // Try changing to isLoggedIn={true}: <Greeting isLoggedIn={false} />, document.getElementById('root') );
要素変数
先ほどの例にあったisLoggedInのように状態を管理するために要素変数を使うことができる。
以下は状態によってコメントとボタンの描画を切り替えています。
class LoginControl extends React.Component { constructor(props) { super(props); this.handleLoginClick = this.handleLoginClick.bind(this); this.handleLogoutClick = this.handleLogoutClick.bind(this); this.state = {isLoggedIn: false}; } handleLoginClick() { this.setState({isLoggedIn: true}); } handleLogoutClick() { this.setState({isLoggedIn: false}); } render() { const isLoggedIn = this.state.isLoggedIn; let button; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} />; } else { button = <LoginButton onClick={this.handleLoginClick} />; } return ( <div> <Greeting isLoggedIn={isLoggedIn} /> {button} </div> ); } } function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } function LoginButton(props) { return ( <button onClick={props.onClick}> Login </button> ); } function LogoutButton(props) { return ( <button onClick={props.onClick}> Logout </button> ); } ReactDOM.render( <LoginControl />, document.getElementById('root') );
論理 && 演算子によるインライン If
ReactでもJavaScriptのtrue && expression は必ず expression と評価され、false && expression は必ず false と評価される
という機能を持ちます。
function Mailbox(props) { const unreadMessages = props.unreadMessages; return ( <div> <h1>Hello!</h1> // 中括弧で囲むことで論理 && 演算子によるインライン Ifを実現 {unreadMessages.length > 0 && <h2> You have {unreadMessages.length} unread messages. </h2> } </div> ); } const messages = ['React', 'Re: React', 'Re:Re: React']; ReactDOM.render( <Mailbox unreadMessages={messages} />, document.getElementById('root') );
条件演算子によるインライン If-Else
JavaScript の condition ? true : false 条件演算子
を利用することで条件演算子によるインライン If-Elseを利用することが可能。
render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in. </div> ); }
コンポーネントのレンダーを防ぐ
他のコンポーネントによってレンダーされているにも関わらず、コンポーネントが自分のことを隠したい場合nullを返すことでそれが可能となる。
そんなことあるのかなと思って検索したら、renderの結果を条件で空にしたい場合nullを返すようにしないとエラーになるからその回避としてらしい。
コンポーネントの render メソッドから null を返してもコンポーネントのライフサイクルメソッドの発火には影響しません。例えば componentDidMount は変わらず呼び出されます。
今日はここまで。
Reactガイドを読んでいくその8
これは
Reactのガイドを読んでいく記事です。
ガイドのリンク
イベント処理
昨日の続きです。
JSXのコールバックにおけるthisの意味に注意が必要。
JavaScriptではクラスのメソッドはデフォルトでバインドされない。
なので、this.handleClickへのバインドをせずにonClickに渡した場合thisはundefindになる。
バインドしない方法として2つある。
CreateReactAppでデフォルト有効になっている、パブリッククラスフィールド構文を使用する方法。
class LoggingButton extends React.Component { // This syntax ensures `this` is bound within handleClick. // Warning: this is *experimental* syntax. handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } }
もう一つはコールバック内でアロー関数を使用する方法。
class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { // This syntax ensures `this` is bound within handleClick return ( <button onClick={(e) => this.handleClick(e)}> Click me </button> ); } }
イベントハンドラに引数を渡す
Reactイベントを表すeという引数はIDの次の2番目の引数として渡される。
// アロー関数がイベントハンドラに追加パラメータを渡す役割 <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> // Function.prototype.bindがパラメータを渡す役割 <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
今日はここまで。
Reactガイドを読んでいくその7
これは
Reactのガイドを読んでいく記事です。
ガイドのリンク
イベント処理
今回も複数回に分けます。
ReactのイベントはcamelCaseで命名される。
JSXではイベントハンドラとして文字列ではなく関数を渡す。
// これはHTML <button onClick="activateLasers()"> Activate Lasers </button> // Reactではこう <button onClidck={activateLasers}> Activate Lasers </button>
Reactでは明示的にpreventDefaultを呼び出さない限りfalseを返してもデフォルトの動作を抑止することができない。
function ActionLink() { function handleClick(e) { // eはsynthetic e.preventDefault(); console.log('The link was clicked.'); } return ( <a href="#" onClick={handleClick}> Click me </a> ); }
synthetic:
合成イベント (SyntheticEvent) – React
少ないですが、今日はここまで。