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にして進めていこうかな~と思いました。