https://github.com/masarufuruya/rails_react_study/blob/master/study3.md
tiqavのAPIを使ってネタ画像をランダムに取得して表示するツールを作ります。 10秒置きに画像は再ロードされます。
- 非同期通信を実装する方法
- タイマーを設定する方法
$ git checkout master
$ git pull origin master
今回は前回まで作っていたシャッフルランチとは別のブランチを作成します。 以下のブランチを作成してください。
$ git checkout -b [名前]_study4
ビルドのコマンドは先に実行しておきましょう。 既にmasterブランチでpackage.jsonに設定しているのですぐに以下のコマンドが実行できます。
$ npm run watch
状態としては画像の一覧があれば良いので、以下のようにfrontend/src/javascripts/App.jsを書き換えます。
class SampleApp extends React.Component {
constructor() {
super()
this.state = {
images: []
}
}
}
まずは動作確認用にJSXとrenderを用意します。
class SampleApp extends React.Component {
constructor() {
super()
this.state = {
images: []
}
}
//追加
render() {
return (
<div>
<h1>ネタ画像検索</h1>
//画像検索結果のコンポーネントを別に置く
</div>
)
}
}
//追加
const elem = React.createElement(SampleApp)
render(elem, document.getElementById('sample'))
具体的な機能を実装する前に次に子コンポーネントを用意します。
frontend/src/javascripts/SearchImages.jsを作成し、内容は以下のようにします。
import React from 'react'
const SearchImages = () => {
//ここにJSXを書く
}
SearchImages.propTypes = {
images: React.PropTypes.array.isRequired
}
module.exports = SearchImages
まずは親コンポーネントから何をpropsで受け取るかを決め、propTypesで定義します。
画像一覧コンポーネントは親から一覧の配列を受け取り、それをさらに画像用のコンポーネントに渡するので受け取るpropsはimagesのみです。
frontend/src/javascripts/SearchImage.jsを作成し、内容は以下のようにします。
import React from 'react'
const SearchImage = () => {
//ここにJSXを書く
}
SearchImage.propTypes = {
imgUrl: React.PropTypes.string.isRequired
}
module.exports = SearchImage
画像用のコンポーネントでは画像パスを元にimgタグを表示するので画像URLをpropsとして受け取ります。
以下のようにJSXを記述します。
const SearchImage = (props) => {
return (
<img className="copy" src={props.imgUrl}/>
)
}
propsを受け取るので、(props)に書き換え、画像パスをpropsで受け取ります。 クラス名は今後の実装で必要になるのでつけています。
以下のようにJSXを記述します。
const SearchImages = (props) => {
return (
<div>
{props.images}
</div>
)
}
StatelessComponentではビュー以外の処理を書くべきではないので、
mapで画像用コンポーネントの配列を生成する処理は親コンポーネントで行い、
それをpropsで受け取るようにしています。
子コンポーネントのpropsを指定してから、次に親から必要な要素を渡すようにしていきます。
frontend/src/javascripts/App.jsのstateに仮の配列を設定します。
constructor() {
super()
//stateを修正
this.state = {
images: [{
id: 1,
imgUrl: 'http://img.tiqav.com/2yS.jpg'
}, {
id: 2,
imgUrl: 'http://img.tiqav.com/2yS.jpg'
}]
}
}
次にrender内を以下のコードに書き換えます。
render() {
const images = this.state.images.map((image) => {
return <SearchImage key={image.id} imgUrl={image.imgUrl}/>
})
return (
<div>
<h1>ネタ画像検索</h1>
<SearchImages images={images}/>
</div>
)
}
また忘れずにコンポーネントのインポートを行うようにしましょう。
import SearchImages from './SearchImages'
import SearchImage from './SearchImage'
2の子コンポーネントを用意するで設定したpropTypesを確認しつつ、必要な値を渡してSearchImage,SearchImagesコンポーネントを出力するようにしています。
Railsを起動して以下の見た目になっていればOK。
以下のコマンドでインストールします。
$ npm i axios --save
AjaxのためだけにJQuery使いたくないのと、プロミスが使えるので 入れておくと後々便利なので、axiosを使うようにしています。
frontend/src/javascripts/App.jsに以下の関数を追加します。
fetchRandomTiqavImages(callback) {
axios.get('/samples/fetch_random_tiqav_images')
.then((response) => {
return callback({status: 'success', response: response.data})
}).catch(() => {
return callback({status: 'error'})
})
}
また冒頭でaxiosのインポート文を追加します。
import axios from 'axios'
frontend/src/javascripts/App.jsのrenderの下に以下のコードを追加します
render() {
...省略
}
componentDidMount() {
this.fetchRandomTiqavImages((data) => {
this.setState({
images: data.response
})
})
}
componentDidMountとはReactコンポーネントがDOMに追加された後に呼ばれるメソッドです。
コンポーネントのライフサイクルと呼ばれる仕組みで、以下の記事が詳しいです。 React.jsのComponent Lifecycle - Qiita http://qiita.com/koba04/items/66e9c5be8f2e31f28461
ちなみにライフサイクルはES6のクラスを使ったClassComponentのみ存在し、 StatelessComponentでは使えません。
Railsを実行して以下のようにランダムが画像が表示されればOKです。
frontend/src/javascripts/App.jsに以下の関数を追加します。
10秒毎に非同期通信を実行し、stateを更新する処理です。
startFetchImagesTimer() {
this.fetchImagesTimer = setInterval(() => {
this.fetchRandomTiqavImages((data) => {
this.setState({
images: data.response
})
})
}, 10000)
}
先程追加したcomponentDidMountの中でタイマーをセットします。 Reactでは非同期通信とタイマー処理といった初期化処理はcomponentDidMountに記述するのが普通です。
componentDidMount() {
this.fetchRandomTiqavImages((data) => {
this.setState({
images: data.response
})
})
//以下を追加
this.startFetchImagesTimer()
}
frontend/src/javascripts/App.jsに以下の関数を追加します。
componentWillUnmount() {
clearInterval(this.startFetchImagesTimer)
}
componentWillUnmountはコンポーネントがDOMから削除された時に呼ばれるメソッドで、 設定したタイマーはこちらで解除するようにしておく必要があります。
この状態でRailsを起動して以下のように10秒毎に画像が変わればOKです。
clipboardというnpmを使うと簡単に実装できるので、自分で作ってみてください。
自分で入力したテキストを元に検索結果を表示するようにしてみましょう。



