これはなに?
React.jsでボタンをおしたら何かを表示するやつを試行錯誤しながらサンプルに追加するチュートリアル のその2です。
前回までで、ボタンをおしたら外部のAPIをたたいて結果を表示するようなサンプルができあがっています。
今度は、前回説明を省略した this
や state
について説明しつつサンプルを変えていきます。
前回から、不要なHTMLの削除や、テキストやコメントを変えているのでご注意ください
下記のコードでApp.js
を書き換えてからnpm start
でサーバを動かして、ブラウザで確認してみましょう。
前回同様の動きになったら次に行ってみましょう。
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<a onClick={this.handleClick}>住所を表示</a>
<p>{this.state.tenki}</p>
</header>
</div>
);
}
handleClick() {
fetch('https://api.zipaddress.net/?zipcode=1000005', {
mode: 'cors'
})
.then(res => {
return res.json();
})
.then(json => {
this.setState({tenki:json.data.fullAddress});
})
}
constructor(props) {
super(props);
this.state = { tenki : "まだ住所をとってません" };
this.handleClick = this.handleClick.bind(this);
}
}
export default App;
状態遷移とかデータの受け渡しとかをしてみる
さて、前回に加えて、もう少しReact.jsっぽいことをチュートリアル的にやってみます。
「郵便番号」の入力ができるようにして、「住所を表示」を押すと、該当の住所が表示される
前回がボタンを押すだけだったのに対して、今回は入力のフォームもつけてみました。
「郵便番号」の入力テキストボックスをつける!
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
{/* ***** テキストボックス ***** */}
<p>郵便番号をいれてください</p>
<p><input type="text" value={this.state.zip_code} /></p>
{/* ***** ここまで ***** */}
<a onClick={this.handleClick}>住所を表示</a>
<p>{this.state.tenki}</p>
</header>
</div>
);
}
handleClick() {
// クエリにinputされたzip_codeを使う
fetch('https://api.zipaddress.net/?zipcode=' + this.state.zip_code, {
mode: 'cors'
})
.then(res => {
return res.json();
})
.then(json => {
this.setState({tenki:json.data.fullAddress});
})
}
constructor(props) {
super(props);
// **** 住所を扱うために zip_code という値をstateに追加
this.state = { tenki : "まだ住所をとってません", zip_code : '1000005' };
this.handleClick = this.handleClick.bind(this);
}
}
export default App;
追加したところ少し詳しく見てみます。
まず<input>
タグを追加しています。これは単なるHTMLなので問題ないですね。input
のvalue
には {this.state.zip_code}
という変数を指定しているところだけ注意です。
value
に使ったthis.state.zip_code
という変数ですが、勝手に使うわけにもいかないので、コンストラクタのところで、this.state =...
に zip_code
の初期値を追加してあります。
そして、最後に、この zip_code
の値がAPIのクエリに使われるようにするために、fetch
のクエリ(URL)書き換えています。
ということで実際起動してクリックしてみるとこんな感じになります。
あれ値が書き換わらないぞ?
やってみればわかりますが、このままだとinput
のところを書き換えようとしても値が書き換わりません。
なぜかというと、value
の値がthis.state.zip_code
になっているからです。
どれだけテキストボックス上で値を書き換えようとしても、value
の値はthis.state.zip_code
になり続けるので、変わることができないのです。 input
には、初期値で入力されたthis.state.zip_code
が表示され続けてしまいます。
ということで、どうするかというと、要は this.state.zip_code
を変えてあげればいいのです。
値が変わるようにする
:
<p><input type="text" value={this.state.zip_code} onChange={(e) => this.setState({zip_code: e.target.value})} /></p>
:
input
にonChange={(e) => this.setState({zip_code: e.target.value})}
を追加します。
つまり何をしているかというと、input
の値がかわるonChange
イベントを使って、値が変わるたびにsetState
を呼び出して値を書き換えていくのです。
これで、無事に値を書き換えることが出来ます。
実際に動かして、郵便番号を変えて住所をとってきてみましょう。
エラー処理してないので存在しない番号をいれてもエラーもなにもでてきません^^
ちょっとだけ色気を出して
値によって処理を変えます。
まあ、たいしたことはしません。 住所が 東京 だったときだけ色を変えるというだけです。
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<p>郵便番号をいれてください</p>
<p><input type="text" value={this.state.zip_code} onChange={(e) => this.setState({zip_code: e.target.value})} /></p>
<a onClick={this.handleClick}>住所を表示</a>
{/* ***** p に style を指定 ***** */}
<p style={this.state.address_style}>{this.state.tenki}</p>
</header>
</div>
);
}
handleClick() {
fetch('https://api.zipaddress.net/?zipcode=' + this.state.zip_code, {
mode: 'cors'
})
.then(res => {
return res.json();
})
.then(json => {
// 東京という文字がはいっているかどうかで style を変更
if ( json.data.fullAddress.indexOf('東京') !== -1 ){
this.setState({address_style:{color:"red"}})
}
else {
this.setState({address_style:{color:"white"}})
}
this.setState({tenki:json.data.fullAddress});
})
}
constructor(props) {
super(props);
this.state = { tenki : "まだ住所をとってません", zip_code : '1000005', address_style : {} };
this.handleClick = this.handleClick.bind(this);
}
}
export default App;
まあ、こんな感じです。
こういうところ1つとってもReact(JSX)はちょっとずつクセがありますね。
style
って普通は文字列
で指定する属性ですけど、JSXでは {}
になってますよね、こういう微妙な差異がなかなか慣れるまでは難しいところです。