Murayama blog.

プログラミング教育なブログ

Reactだけ学ぶハンズオン 5/5

Part5 Welcome - ハンズオン

ここでは入力した内容を表示するReactアプリケーションを作成します。

20170915200531

開発は以下の手順で進めます。

  1. ライブラリの設定
  2. コンポーネント仕様を定義
  3. コンポーネントクラスをレンダリング

1. ライブラリの設定

titleタグ以外は前章と同じです。ファイル名は05_welcome.htmlという名前で保存しておきます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 05</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  </script>
</body>
</html>

2. コンポーネント仕様を定義

ここでは以下のコンポーネントを作成します。

  • Welcome
    • GreetingList
      • GreetingItem(*)
    • Echo

コンポーネント仕様は次のようになります。

class GreetingItem extends React.Component {
  render() {
  }
}

class GreetingList extends React.Component {
  render() {
  }
}

class Echo extends React.Component {
  constructor(props) {
  }

  echo(e){
  }

  isEnterKey(e){
  }

  render() {
  }
}

class Welcome extends React.Component {
  constructor(props) {
  }

  save(completeName){
  }

  echo(incompleteName){
  }

  render(){
  }
}

コードが長くなるので順に見ていきましょう。まずはGreetingItemとGreetingListです。

class GreetingItem extends React.Component {
  render() {
    return (
      <li>Hello {this.props.name}</li>
    );
  }
}

class GreetingList extends React.Component {
  render() {
    var greetingItems = this.props.names.map(function(name, i){
        return <GreetingItem name={name} key={i} />;
    });

    return (
      <div>
        <h1>Welcome to Webz</h1>
        <ul>{greetingItems}</ul>
      </div>
    );
  }
}

GreetingItem、GreetingListについては以前に作成した内容と同じです。GreetingListのnamesプロパティに名前の配列を設定することで、個々の名前が子要素のGreetingItemのnameプロパティに設定されます。

つづいてEchoコンポーネントです。

class Echo extends React.Component {
  constructor(props) {
    super(props);
    // bind this
    this.echo = this.echo.bind(this);
    this.isEnterKey = this.isEnterKey.bind(this);
  }

  echo(e){
    this.props.onChange(e.target.value);
  }

  isEnterKey(e){
    if (e.keyCode == 13) {
      this.props.onSave(e.target.value);
    }
  }

  render() {
    return (
      <div>
        <h3>Please type your name.</h3>
        <input type="text" onChange={this.echo} onKeyDown={this.isEnterKey} value={this.props.name}/>
        <h3>{this.props.name}</h3>
      </div>
    );
  }
}

Echoコンポーネントは以前に作成したものと以下の点で異なります。

  1. ステートnameではなく、プロパティnameを使用している
  2. echoメソッドの実装でステートの更新ではなく、onChangeプロパテイ(関数)を呼び出している
  3. onKeyDownイベントハンドラでisEnterKeyメソッドを呼び出している

1. ステートnameではなく、プロパティnameを使用している

Reactで、複合コンポーネントを作成する場合、可能な限りステートの管理は親コンポーネントで管理するようにします。

  • Welcome
    • GreetingList
      • GreetingItem(*)
    • Echo

上記の場合、ステートはWelcomeコンポーネントで管理すべきです。従って入力中の名前を示すnameプロパティをWelcomeコンポーネントで定義し、代わりにEchoコンポーネントには、Welcomeコンポーネントとの外部インタフェースとなるnameプロパティを用意します。親コンポーネントのステートの変更をnameプロパティ経由で受け取るようにします。

render() {
  return (
    <div>
      <h3>Please type your name.</h3>
      <input type="text" onChange={this.echo} onKeyDown={this.isEnterKey} value={this.props.name}/>
      <h3>{this.props.name}</h3>
    </div>
  );
}

2. echoメソッドの実装でステートの更新ではなく、onChangeプロパテイ(関数)を呼び出している

Echoコンポーネントからnameステートを排除したので、echoメソッドの実装は次のようにonChangeプロパティを呼び出すようにします。

echo(e){
  this.props.onChange(e.target.value);
}

Echoコンポーネントを利用する親コンポーネント(今回の場合Welcomeコンポーネント)では次のようにプロパティを指定します。

<Echo name={this.state.name} onChange={this.foo} onSave={this.bar}/>

この場合、onChangeプロパティにWelcomeコンポーネントで指定したfooメソッドを指定してます。結果として、EchoコンポーネントでonChangeイベントが発生するとこのfooメソッドが呼ばれることになります。

3. onKeyDownイベントハンドラでisEnterKeyメソッドを呼び出している

onKeyDownイベントハンドラのisEnterKeyメソッドは次のようになっています。

isEnterKey(e){
  if (e.keyCode == 13) {
    this.props.onSave(e.target.value);
  }
}

キーコード:13とはEnterキーを意味しています。つまり、Enterキーが入力された場合、onSaveプロパティ(関数)を呼び出すようにしています。

たとえば、以下のようにEchoコンポーネントを定義しとしましょう。

<Echo name={this.state.name} onChange={this.foo} onSave={this.bar}/>

Enterキークリック時に、onSaveプロパティで指定されたbarメソッドが呼び出されることになります。

さいごに親コンポーネントとなるWelcomeのコンポーネント仕様を実装します。

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      names: this.props.names,
      name: ""
    };
    // bind this
    this.save = this.save.bind(this);
    this.echo = this.echo.bind(this);
  }

  save(completeName){
    var names = this.state.names.concat(completeName);
    this.setState({
      names: names,
      name: ""
    });
  }

  echo(incompleteName){
    this.setState({name: incompleteName});
  }

  render(){
    return(
      <div>
        <GreetingList names={this.state.names} />
        <Echo name={this.state.name} onChange={this.echo} onSave={this.save}/>
      </div>
    );
  }
}

constructorで初期ステートを指定します。ステートはnames配列と、name文字列の2つです。namesステートはGreetingListコンポーネントのnamesプロパティに指定し、nameステートはEchoコンポーネントのnameプロパティに指定します。

echoメソッド、saveメソッドはステートを更新します。これらのメソッドはEchoコンポーネントイベントハンドラに指定しているので、Echoコンポーネントにおいて、イベントが発生時するとコールバックされます。

renderメソッドではGreetingListと、Echoコンポーネントレンダリングしています。renderメソッドは単一のコンポーネントを返す必要があるので、divタグでラップしています。

3. コンポーネントクラスをレンダリング

作成したコンポーネントクラス(Welcome)を画面にレンダリングします。

var names = ["Murayama", "Takahashi", "Sanada"];
ReactDOM.render(
  <Welcome names={names} />,
  document.getElementById('example')
);

Welcomeコンポーネントのnamesプロパティに3件の名前を指定します。こうすることで、画面描画時の初期値として表示されます。

ここまでの作業をまとめると次のようになります。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 05</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  class GreetingItem extends React.Component {
    render() {
      return (
        <li>Hello {this.props.name}</li>
      );
    }
  }

  class GreetingList extends React.Component {
    render() {
      var greetingItems = this.props.names.map(function(name, i){
          return <GreetingItem name={name} key={i} />;
      });

      return (
        <div>
          <h1>Welcome to Webz</h1>
          <ul>{greetingItems}</ul>
        </div>
      );
    }
  }

  class Echo extends React.Component {
    constructor(props) {
      super(props);
      // bind this
      this.echo = this.echo.bind(this);
      this.isEnterKey = this.isEnterKey.bind(this);
    }

    echo(e){
      this.props.onChange(e.target.value);
    }

    isEnterKey(e){
      if (e.keyCode == 13) {
        this.props.onSave(e.target.value);
      }
    }

    render() {
      return (
        <div>
          <h3>Please type your name.</h3>
          <input type="text" onChange={this.echo} onKeyDown={this.isEnterKey} value={this.props.name}/>
          <h3>{this.props.name}</h3>
        </div>
      );
    }
  }

  class Welcome extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        names: this.props.names,
        name: ""
      };
      // bind this
      this.save = this.save.bind(this);
      this.echo = this.echo.bind(this);
    }

    save(completeName){
      var names = this.state.names.concat(completeName);
      this.setState({
        names: names,
        name: ""
      });
    }

    echo(incompleteName){
      this.setState({name: incompleteName});
    }

    render(){
      return(
        <div>
          <GreetingList names={this.state.names} />
          <Echo name={this.state.name} onChange={this.echo} onSave={this.save}/>
        </div>
      );
    }
  }

  var names = ["Murayama", "Takahashi", "Sanada"];
  ReactDOM.render(
    <Welcome names={names} />,
    document.getElementById('example')
  );
  </script>
</body>
</html>

Reactだけ学ぶハンズオン 4/5

Part4 Echo - ハンズオン

ここでは入力した内容を表示するReactアプリケーションを作成します。

20170915200536

開発は以下の手順で進めます。

  1. ライブラリの設定
  2. コンポーネント仕様を定義
  3. コンポーネントクラスをレンダリング

1. ライブラリの設定

titleタグ以外は前章と同じです。ファイル名は04_echo.htmlという名前で保存しておきます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 04</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  </script>
</body>
</html>

2. コンポーネント仕様を定義

ここでは画面の入力を受け付けるテキストボックスと、入力された名前を表示する領域を持ったとEchoコンポーネントクラスを作成します。

Echoコンポーネントの仕様は以下のとおりです。

class Echo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: ""};
    // bind this
    this.echo = this.echo.bind(this);
  }

  echo(e){
    this.setState({name: e.target.value});
  }

  render() {
    return (
      <div>
        <h1>Welcome to WEBZ.</h1>
        <h3>Please type your name.</h3>
        <input type="text" onChange={this.echo} />
        <h3>{this.state.name}</h3>
      </div>
    );
  }
}

renderメソッド以外にconstructor、echoメソッドの2つが追加されています。constructorの説明に入る前にReactのステートについて学習しておきましょう。

Reactにはステートという仕組みがあります。ステートとはコンポーネントの状態を表すものです。上記のEchoコンポーネントには「(入力された)名前」を示すnameというステートがあります。Reactのコンポーネントはステートの内容が更新されると自動的に再描画(renderメソッド呼び出し)されるようになっています。

constructorはReactコンポーネントのライフサイクルメソッドの1つで、コンポーネントインスタンスの生成時に呼び出されます。constructorでステートの初期値を設定できます。

constructor(props) {
  super(props);
  this.state = {name: ""};
  // bind this
  this.echo = this.echo.bind(this);
}

上記のコードではnameステートの初期値を空文字で設定しています。

this.echo = this.echo.bind(this); は後の echoメソッド を利用できるようにしています。

つづいてechoメソッドを見てみましょう。

echo(e){
  this.setState({name: e.target.value});
}

echoメソッドはReactの仕組みに依存したものではなく、アプリケーション独自のメソッドです。echoメソッドはrenderメソッドの中でinputタグのonChangeイベントハンドラに関連付けられています。

<input type="text" onChange={this.echo} />

これによって、テキストボックスの値に変化が生じるとechoメソッドが呼び出されるようになります。echoメソッドの中では、コンポーネントのステートを更新するためにsetStateメソッドを呼び出しています。Reactは内部で仮想DOMによってコンポーネントを管理しているため、ステートを更新する場合、必ずsetStateメソッドを使用する必要があります。*1

echoメソッドによってステートが更新されるとコンポーネントのrenderメソッドがReactによって呼び出されます。

render() {
  return (
    <div>
      <h1>Welcome to WEBZ.</h1>
      <h3>Please type your name.</h3>
      <input type="text" onChange={this.echo} />
      <h3>{this.state.name}</h3>
    </div>
  );
}

これによってテキストボックスに入力した内容が即座に画面に表示されるようになります。

3. コンポーネントクラスをレンダリング

作成したコンポーネントクラス(Echo)を画面にレンダリングします。

ReactDOM.render(
  <Echo />,
  document.getElementById('example')
);

Echoコンポーネントにプロパティの指定はありません。

ここまでの作業をまとめると次のようになります。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 04</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">

  class Echo extends React.Component {
    constructor(props) {
      super(props);
      this.state = {name: ""};
      // bind this
      this.echo = this.echo.bind(this);
    }

    echo(e){
      this.setState({name: e.target.value});
    }

    render() {
      return (
        <div>
          <h1>Welcome to WEBZ.</h1>
          <h3>Please type your name.</h3>
          <input type="text" onChange={this.echo} />
          <h3>{this.state.name}</h3>
        </div>
      );
    }
  }

  ReactDOM.render(
    <Echo />,
    document.getElementById('example')
  );
  </script>
</body>
</html>

*1:this.state.name = e.target.value; のように記述してはいけません。

Reactだけ学ぶハンズオン 3/5

Part3 GreetingList - ハンズオン

ここでは次のようなメッセージ一覧を表示するReactアプリケーションを作成します。

20170915200541

開発は以下の手順で進めます。

  1. ライブラリの設定
  2. コンポーネント仕様を定義
  3. コンポーネントクラスをレンダリング

1. ライブラリの設定

titleタグ以外は前章と同じです。ファイル名は03_greeting_list.htmlという名前で保存しておきます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 03</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  </script>
</body>
</html>

2. コンポーネント仕様を定義

Reactのコンポーネントクラスを定義するために、コンポーネント仕様を作成します。*1ここではHelloと挨拶するGreetingItemクラスと、複数のGreetingItemを管理するGreetingListクラスを定義します。

GreetingItemクラスは以下のとおりです。

class GreetingItem extends React.Component {
  render() {
    return (
      <li>Hello {this.props.name}</li>
    );
  }
}

前章で作成したGreetingクラスとほとんど同じです。nameプロパティの内容をレンダリングします。

続いてGreetingListクラスです。

class GreetingList extends React.Component {
  render() {
    var greetingItems = this.props.names.map(function(name, i){
        return <GreetingItem name={name} key={i} />;
    });

    return (
      <div>
        <h1>Welcome to Webz</h1>
        <ul>{greetingItems}</ul>
      </div>
    );
  }
}

GreetingListコンポーネントはnamesプロパティから名前の配列を受け取ります。実際の値の受け渡しは後のrenderフェーズで指定します。

renderメソッドではnamesプロパティをループして、JSXを使ってGreetingItem要素を定義しています。Reactは仮想DOMを使って要素を管理しているので、各要素にはkey属性を指定して一意な値を定義する必要があります。

3. コンポーネントクラスをレンダリング

作成したコンポーネントクラス(GreetingList)を画面にレンダリングします。GreetingListコンポーネントにnamesプロパティを指定している点を確認しておいてください。

var names = ["Murayama", "Takahashi", "Sanada"];
ReactDOM.render(
  <GreetingList names={names} />,
  document.getElementById('example')
);

ここまでの作業をまとめると次のようになります。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 03</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  class GreetingItem extends React.Component {
    render() {
      return (
        <li>Hello {this.props.name}</li>
      );
    }
  }

  class GreetingList extends React.Component {
    render() {
      var greetingItems = this.props.names.map(function(name, i){
          return <GreetingItem name={name} key={i} />;
      });

      return (
        <div>
          <h1>Welcome to Webz</h1>
          <ul>{greetingItems}</ul>
        </div>
      );
    }
  }

  var names = ["Murayama", "Takahashi", "Sanada"];
  ReactDOM.render(
    <GreetingList names={names} />,
    document.getElementById('example')
  );
  </script>
</body>
</html>

*1:コンポーネントクラスを作成します。でいいような気が。

Reactだけ学ぶハンズオン 2/5

Part2 Greeting - ハンズオン

ここでは次のようなメッセージを表示するReactアプリケーションを作成します。*1

20170915200544

開発は以下の手順で進めます。

  1. ライブラリの設定
  2. コンポーネント仕様を定義
  3. コンポーネントクラスをレンダリング

1. ライブラリの設定

titleタグ以外は前章と同じです。ファイル名は02_greeting.htmlという名前で保存しておきます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 02</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  </script>
</body>
</html>

2. コンポーネント仕様を定義

Reactのコンポーネントクラスを定義するために、コンポーネント仕様を作成します。

class Greeting extends React.Component {
  render() {
    return (
      <div>
        <h1>Welcome to Webz</h1>
        <h2>Hello {this.props.name}</h2>
      </div>
    );
  }
}

renderメソッドではJSXを使ってコンポーネントを定義していますが、h2タグの中で{this.props.name}を指定しています。これはReactのプロパティという仕組みを使っています。プロパティとはReactコンポーネントの外部インタフェースです。ここでは外部から指定されたnameプロパティを表示するようにしています。nameプロパティの指定は、後のレンダリング時に指定します。

3. コンポーネントクラスをレンダリング

作成したコンポーネントクラス(Greeting)を画面にレンダリングします。前章とほとんど同じですが、Greetingコンポーネントにnameプロパティを指定している点を確認しておいてください。

var name = "Murayama";
ReactDOM.render(
  <Greeting name={name} />,
  document.getElementById('example')
);

ここまでの作業をまとめると次のようになります。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 02</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  class Greeting extends React.Component {
    render() {
      return (
        <div>
          <h1>Welcome to Webz</h1>
          <h2>Hello {this.props.name}</h2>
        </div>
      );
    }
  }

  var name = "Murayama";
  ReactDOM.render(
    <Greeting name={name} />,
    document.getElementById('example')
  );
  </script>
</body>
</html>

*1:Webzてのは勉強会(コミュニティ)の名前です。気にせずに。。

Reactだけ学ぶハンズオン 1/5

Reactとは

ReactはUIをつくるためのJavaScriptライブラリです。

  • Declarative
    • 宣言的なプログラミング(たとえばExcelのsum関数みたいな仕組み)
  • Component-Based
  • Learn Once, Write Anywhere
    • 一度学べば、どこでも動く(詳しくはRact Native)

Part1 Hello React - ハンズオン

ここでは次のような画面にHello Worldと表示するReactアプリケーションを作成します。

20170915200549

開発は以下の手順で進めます。

  1. ライブラリの設定
  2. コンポーネント仕様を定義
  3. コンポーネントクラスをレンダリング

1. ライブラリの設定

Reactで配布されてるreact.js、react-dom.jsを使用します。

<script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
<script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>

また、JSXをサポートするためにBabelを使用します。

<script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>

ここまでの作業をまとめると以下のとおりです。ファイル名は01_hello.htmlという名前で保存しておきます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 01</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
</body>
</html>

2. コンポーネント仕様を定義

これからJavaScriptをゴリゴリ記述していくので、HTMLファイルのbodyタグの中にdivタグとscriptタグを定義します。scriptタグのtype属性にはtext/babelを指定してください。これでJSXシンタックスが利用できます。

<body>
  <div id="example"></div>
  <script type="text/babel">
  </script>
</body>

divタグはこれから作成するコンポーネントのコンテナとなる要素です。

ここでは画面にHello Worldと出力するコンポーネント仕様を定義し、コンポーネントクラスHelloWorldを作成します。ReactはコンポーネントをJSXで定義可能です。

scriptタグの中に以下のコードを記述します。

class HelloWorld extends React.Component {
  render() {
    return <h1>Hello World</h1>;
  }
}

ここではes6(ES2015)のオブジェクト指向構文から導入されたclass命令を使ってクラスを定義しています。ここで定義したHelloWorldクラスはReact.Componentを継承しています。このようなクラスはReactコンポーネントと呼ばれます。Reactコンポーネントには必ずrenderメソッドを定義しなくてはいけません。

コンポーネントとは部品という意味です。

renderメソッドの内部では、戻り値がHTMLのようになっています。このような表記法はJSXと呼ばれ、コンポーネントを手軽に記述することができます。JSXをサポートするにはbabelライブラリを読み込む必要があります。JSXの利用は任意です。

3. コンポーネントクラスをレンダリング

作成したコンポーネントクラスを画面にレンダリングします。ReactDOM.renderメソッドの引数にコンポーネントクラス、コンポーネントのコンテナとなるDOM要素を指定します。

ReactDOM.render(<HelloWorld />, document.getElementById('example'));  

ここまでの作業をまとめると次のようになります。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello React 01</title>
  <script src="https://unpkg.com/react@15.6.1/dist/react.js" charset="utf-8"></script>
  <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.js" charset="utf-8"></script>
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
</head>
<body>
  <div id="example"></div>
  <script type="text/babel">
  class HelloWorld extends React.Component {
    render() {
      return <h1>Hello World</h1>;
    }
  }

  ReactDOM.render(<HelloWorld />, document.getElementById('example'));  
  </script>
</body>
</html>

新米PHPerのための5つのAtomパッケージ

今年もITエンジニア育成の新入社員研修に取り組んでいます。日々の空前絶後のハードなトレーニングのおかげで今年も優秀なPHPerたちがたくさん育っています。

慣れないプログラミングの習得に苦労しつつもポジティブにがんばっているみなさんへ。PHP初心者が効率良くPHPプログラミングを習得するためのAtomパッケージを紹介します。

linter-php

PHPの構文エラーを見つけてくれます。

atom.io

インストールの途中、依存パッケージも求められるので忘れずにインストールします。AtomのLinterパッケージはHTMLやCSSなど様々な言語に対応しているので必要に応じて探してみると良いです。

indent-guide-improved

インデント範囲をわかりやすく表示してくれます。

atom.io

プログラミングを理解できない人の多くはインデントを意識できていません。インデントを徹底すれば条件分岐の範囲や繰り返しの範囲も明確になります。プログラミングに慣れないうちはインデントを見やすくすると良いです。

あとAtomのデフォルト機能のAuto Indentも上手くつかいましょう。

show-ideographic-space

全角スペースを表示してくれます。

atom.io

これで、よくある全角スペース混入エラーともおさらばです。

atom-autocomplete-php

PHPコードの自動補完が強化されます。

atom.io

デフォルトの補完も便利ですが、関数の引数なども表示してくれるのでコーディングがさらに捗ります。

事前にPHPのパッケージ管理ツールであるComposerをインストールしておかないと起動時にアラートが出るようです。最初は無視しておいてもいいですが、気になる方はComposerをセットアップしてAtomatom-autocomplete-php パッケージの設定画面でcomposerのPATHを指定する必要があります。 https://getcomposer.org/

php-debug

Xdebugデバッグできるようになります。

atom.io

困ったときはデバッグしましょう。インストールはちょっとややこしいので詳しくは以下の記事で。

murayama.hatenablog.com

おまけ

私が普段使ってるAtomパッケージはこちらで確認できます。

https://atom.io/users/murayama333/stars

activate-power-modeはAtom使っているなら常識だし、個人的にはgist-itとか毎日のように使っています。scriptも昨日入れてみたけど便利だった。

ちなみにAtomにはapmコマンドというパッケージ管理のコマンドが付いています。apmでパッケージ管理すると上記のページのように、お気に入りのパッケージにスターをつけて管理できます。仲間と便利なパッケージを共有したり、別の端末に同じ設定でAtomパッケージをインストールしたり、いろいろできるので触ってみると楽しいと思います。

AtomでXdebugを使ってステップ実行するには

Xdebugをインストールします。

https://xdebug.org/

Xdebugは実行環境やPHPのバージョンによってインストールの手順が異なるので、以下のURLからインストール手順を確認します。

https://xdebug.org/wizard.php

ローカルで php -i した出力結果を上記のページにコピペします。

私の環境(Mac)だと以下のようになりました。Windowsだともっと簡単で、dll落とすだけで済むっぽい。

手順に従ってインストールします。

Xdebugの設定

続いてphp.iniにXdebugの設定を追記します。

[xdebug]
xdebug.remote_enable=1
xdebug.remote_host=127.0.0.1
xdebug.remote_connect_back=off
xdebug.remote_port=9000
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_autostart=true

以降ビルトインサーバの起動時には9000番ポートを使うようにします。

php -S localhost:9000

Atomの設定

Atomの拡張パッケージであるphp-debugをインストールします。

https://atom.io/packages/php-debug

インストールが完了すると、AtomのフッターにPHP Debugのアイコンが表示されます。

動作確認

適当なPHPプログラムを書きます。sample.php

<?php
$message = "Hello World";
for ($i=0; $i < 10; $i++) {
  echo $message;
}

上記の4行目(行番号の横)をクリックしてブレークポイントを設定します。またAtomのフッターからPHPDebugアイコンからデバッグ用のウィンドウを表示しておきます。デバッグ用のウィンドウを表示しておかないとブレークポイントは有効にならないので注意です。

PHPプログラムを実行します(ビルトインサーバで動かしてもOK)。

php sample.php

ブレークポイントでコードの実行が停止するので、デバッグ用のウィンドウでコード実行を制御できます。