CreateReactApp編(1)|React使ってSPAを作るよの続きです。
CreateReactAppで構築したプロジェクトに既存のソースを移す
さっそく既存のソースを移します。
とりあえずcomposer.jsonとか/resourcesディレクトリとか、Laravel側で必要なファイルはそのままコピーしてきます。
さらにjsxファイルもsrcディレクトリに入れちゃいます。
create-react-appで作られたサンプルのソースは、.jsxではなく、.jsファイルですね。
ES6で書かれているようです。
つい先日TypeScriptの導入に挑戦したところなので、classの書き方はなんとなく見覚えがある感じです。
まずはエントリーポイントとなるIndex.jsを見ていきます。
(もとのプロジェクトではapp.jsxでしたがわかりやすいようにリネームしました。)
//Index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import SiteHeader from './SiteHeader';
import ArticleArea from './ArticleArea';
import SiteFooter from './SiteFooter';
//メインコンポーネント
class Main extends Component {render() {
return (
<main>
<ArticleArea />
</main>
);
}
}
//bodyコンポーネント
class Body extends Component {render() {
return (
<div id="container">
<SiteHeader />
<Main />
<SiteFooter />
</div>
);
}
}
/* React + JSX */
ReactDOM.render(
<Body />,
document.getElementById('body')
);
まず、サンプルアプリに倣ってReactとReactDOMをimportします。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
Reactのところで{Component}をわざわざ指定していますね。
これはTypeScriptをやったときに型付きで
class Main extends React.Component<any,any>
としていたところが
こういうふうに書くようになっています。
class Main extends Component
う~ん。
var Main = React.createClass class Main extends React.Component class Main extends Component
ってな具合に書き方が変わってきていますね。
そして、ほかのjsファイルからコンポーネントをimportします。
import SiteHeader from './SiteHeader'; import ArticleArea from './ArticleArea'; import SiteFooter from './SiteFooter';
あとはほとんど変わりませんね。
render()の中身はこれまでJSXで書いてきたのとほぼ同じように書けます。
ES6で書くときに気を付けないといけないこと
Index.jsは簡単に済みましたが、ほかのファイルはそう簡単にはいきません。
たとえば、Tag.jsですが…
こういったコンポーネントがあります。
//タグ
class Tag extends Component {
constructor(props) {
super(props)
this.handleAjax = this.handleAjax.bind(this);
}
handleAjax() {
apiURL = './api/article?tag=' + this.refs.tag.name;
$('.overlay').removeClass('overlay');
$('#overlay').css('display', 'none');
$('#overlay-close').css('display', 'none');
$('#spinner').css('display', 'block');
}
render() {
return (
<li><a ref="tag" name={this.props.id} onClick={this.handleAjax}>{this.props.tag}</a></li>
)
}
}
パッと見大きく異なるのは、constructorですね。
TypeScriptのときにもハマったように、onClickのイベントについて、constructorでthisをbindする必要があります。
あとは、関数のところの書き方も、これまで
handleAjax: function(){
となっていたところが、
handleAjax(){
だけでいけるようになりました。
閉じ括弧のあとのカンマも不要です。
それからもうひとつ。
これまでJSONで取得してきたデータをリストコンポーネントに渡すところで、データを格納するdataの初期化をgetInitialStateで行っていました。
それも、constructorで指定することになります。
//記事リストコンポーネント
export default class ArticleArea extends Component {
//JSONデータ取得
constructor(props) {
super(props)
this.state = {
data: []
};
this.fetchURL = this.fetchURL.bind(this);
this.loadArticleFromServer = this.loadArticleFromServer.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
}
//略
loadArticleFromServer() {
var t = this;
$.ajax({
url: apiURL,
dataType: 'json',
cache: false,
timeout: 10000
}).done(function(data) {
t.setState({data: data});
//略
render() {
var articleNodes = this.state.data.map(function(article) {
//略
・・・といった修正を全体にかけたらできあがりです!
GitHubにソースあげておきました。
https://github.com/mayo31/minami-create-react-app
開発環境の依存関係がだいぶスッキリしますし、特に問題なさそうだったら、これをmasterにして進めていこうかな~と思いました。