太陽がまぶしかったから

C'etait a cause du soleil.

React 入門 その1 React Component の表示と繰り返し制御

はじめての React

 上記で構築した Docker 環境で Laravel x React に入門してみる。 基本的には resources/views/welcome.blade.php から紐づけた resources/assets/js/components/Example.js を編集していく。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class App extends Component {
    render() {
        return (
            <div>
                <h1>会社管理</h1>
                <CompanyInput />
            </div>
        );
    }
}

class CompanyInput extends Component {
    render() {
        return (
            <div><input placeholder="会社名" /> <button>登録</button></div>
        );
    }
}

if (document.getElementById('example')) {
    ReactDOM.render(<App />, document.getElementById('example'));
}

f:id:bulldra:20180505204141j:plain

 基本的には Component を継承した class の render() で JSX をreturn する形でコンポーネントを作成し。作成したコンポーネントは別のコンポーネントの JSX 内から利用できるので、親子関係で最終的な表示定義を作成して ReactDOM で現実のDOMに紐付けると理解。

React Component の引数

 React Component への引数はタグの属性または子要素で定義する。タグの属性に {} で引数を指定するとコンポーネントクラスの this.props 配下に格納される。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class App extends Component {
    render() {
        
        return (
            <div>
                <h1>会社管理</h1>
                <CompanyInput placeholder={ "会社名を入れてね" }/>
            </div>
        );
    }
}

class CompanyInput extends Component {
    render() {
        return (
            <div><input placeholder={ this.props.placeholder } /> <button>登録</button></div>
        );
    }
}


if (document.getElementById('example')) {
    ReactDOM.render(<App />, document.getElementById('example'));
}

f:id:bulldra:20180505205337j:plain

 JSXのタグ全体の文字列はもちろん、属性値も " で囲わない記法に違和感を感じつつも、下手にクォートさせてもバグの温床になるだけという割り切りが React の特徴らしいので慣れの問題か。

React Component 内での繰り返し記法

 React Component 内で繰り返しを行うには Array.prototype.map() 関数の理解が必要になる。 map 関数とは配列の要素ごとにコールバック関数を実行する関数。Component の引数として受け取った配列の要素ごとに JSX を返却する関数を定義することで繰り返しを実現する。

class App extends Component {
    render() {
        const companies = [
            {company_name:'株式会社React', company_id: 1 },
            {company_name:'株式会社Vue', company_id: 2 },
            {company_name:'Angular株式会社', company_id: 3 },
        ];        
        return (
            <div>
                <h1>会社管理</h1>
                <CompanyInput placeholder={ "会社名を入れてね" }/>
                <CompanyList companies={ companies } />
            </div>
        );
    }
}

class CompanyInput extends Component {
    render() {
        return (
            <div><input placeholder={ this.props.placeholder } /> <button>登録</button></div>
        );
    }
}

class CompanyList extends Component {
    render() {
        const companiesMap = this.props.companies.map(c => {
            return <li key={c.company_id}>{ c.company_name }</li>; 
        });
    
        return (
            <ol>{ companiesMap }</ol>
        );
    }
}

f:id:bulldra:20180505211207j:plain

 companies の要素を <li> タグに変換する map 関数の定義を companiesMap に格納して、 JSX 内で展開している。DOMに対して繰り返しで子要素を追加する場合には key 属性が必要となるため company_id を割りあてている。

状態を持つ必要のないコンポーネントは SFC 化

 会社情報をテーブルで表示する場合は会社要素自体をコンポーネント化したいが、都度でコンポーネントクラスを作っていくと、とり得る状態の組み合わせが複雑化していくし、状態変更に応じた処理が重くなっていくため、画面上での状態を持つ必要がないコンポーネントについては、Stateless Functional Components 化すべきとのこと。

class CompanyList extends Component {
    render() {
        const companiesMap = this.props.companies.map(c => {
            return <CompanyItem key={c.company_id}  { ...c } />; 
        });
    
        return (
            <table>
                <thead>
                    <tr><th>会社ID</th><th>会社名</th></tr>
                </thead>
                <tbody>
                    { companiesMap }
                </tbody>
            </table>
        );
    }
}

function CompanyItem (props) {
    return (
        <tr>
            <td>{ props.company_id }</td>
            <td>{ props.company_name }</td>
        </tr>
    );
}

 上記の CompanyItem() のように props を関数の引数として受け取って、そのまま JSX を返却するだけ。 props を変更しても影響ないが、やっても仕方がないだろう。

f:id:bulldra:20180505213449j:plain

  return <CompanyItem key={c.company_id} { ...c } />; の { ...c } はオブジェクトの要素を展開するスプレッド演算子。 return <CompanyItem key={c.company_id} company_name={c.company_name} company_id={c.company_id} />; と同じ意味となる。

 とりあえず、静的な JSX の表示処理はなんとなく理解できたので、コンポーネント状態の定義と状態に応じた表示処理について実装していく。