Murayama blog.

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

Jupyter Notebookで始める機械学習プログラミング

これからPython機械学習始めたい方向けのまとめです。

Python

PythonはWebアプリの開発からちょっとしたツールの開発まで、多目的に利用できるプログラミング言語です。また機械学習ライブラリが充実しているため近年注目を集めています。

www.python.org

次のAnacondaディストリビューションPythonをインストールすることもできます。

Anaconda

Python機械学習を始めるにはCONTINUUM社の配布しているはAnacondaディストリビューションを活用すると良いでしょう。以下のURLからダウンロートすることができます。

www.anaconda.com

AnacondaにはPython本体だけでなく機械学習に必要なライブラリも梱包されているため、Anacondaをインストールすればすぐに機械学習プログラミングを始めることができます。

Jupyter Notebook

AnacondaにはJupyter Notebookというブラウザ上で動作するPython開発環境も付属しています。ターミナル(コマンドプロンプト)上で jupyter-notebook コマンドを実行するとローカルでサーバプログラムが起動し、ブラウザが起動します。

jupyter.org

Jupyter Notebookの起動方法について補足しておきます。Anacondaインストール後、Windowsでは画面左下のWindowsメニューから「jupyter-notebook」とタイプするとアプリが見つかります。Macでは、ターミナル上でjupyter-notebookコマンドをタイプします。Jupyter Notebookはデフォルトで8888番ポートを使って起動します。ブラウザで http://localhost:8888/ にアクセスすると開発画面が表示されるでしょう。

Jupyter Notebookでは、ノートブックという形式でファイルを作成できます。ノートブックにはPythonコードや実行結果だけでなく、Markdown形式で文章を挿入することもできるので、データ分析の評価レポートを作成しやすいようになっています。またノートブックファイルは拡張子.ipynbという形式保存されます。.ipynbファイルはGitHubやGistなどでも表示できます。

クラウド上でJupyter Notebookを起動する

Jupyter Notebookの実体はブラウザで利用するWebアプリケーションです。そのためサーバ上でJupyter Notebookを起動すれば、手元のパソコンのブラウザからサーバ上でPythonプログラムを実行することも可能です。

ここではあらかじめJupyter環境をインストール済みのDockerコンテナを起動する方法を紹介します。またDeepLearning開発を支援するPaaS型サービスであるFloydHubを紹介します。

DockerでJupyter環境を構築するには

ここではクラウド環境としてAWSのEC2インスタンスUbuntu / Small)があるものとします。

sshでEC2インスンタンスにログインします。まずUbuntuのパッケージ情報を更新しておきます。

sudo apt update

次にDockerをインストールします。

sudo apt install docker.io -y

Dockerコンテナ(murayama333/ai-prog)を起動します。

sudo docker run -p 8888:8888 --name ai-prog -it murayama333/ai-prog

Dockerの出力ログにURLが表示されます。URLはlocalhostとなっているので、EC2のグローバルIPに置き換えてアクセスすると完了です。

ここで利用したDockerイメージはこちらの記事を参考に作っています。勉強になりました。

dr-asa.hatenablog.com

FloydHubで開発する

Dockerを使えばあっという間に開発環境を構築できますが、FloydHubを使えばもっと手軽にJupyter環境を整えることもできます。

FloydHub - Deep Learning Platform - Cloud GPU

FloydHubを一言で説明するなら

FloydHub is Heroku for DL

FloydHubはDeepLearningのためのHerokuです。つまり、DeepLearningのためのPaaS(Platform as a Service)です。FloydHubの素晴らしいところは、クラウド上ですぐに開発&実行ができるだけでなく、GPUインスタンスを利用することができる点です。無料アカウントの場合、GPUインスタンスは 2時間 / 月 まで利用できます。

FloydHub - Deep Learning Platform - Cloud GPU

FloydHub上でアカウントを作成後、開発キット(floyd-cli)をインストールします。

pip install -U floyd-cli

pipはPythonライブラリの追加コマンドです。pipコマンドを利用するにはローカルにPythonがインストールされている必要があります。

floydコマンドが有効になるので、FloydHubにログインします。

$ floyd login

以下、オフィシャルのクイックスタートを参考に動かしてみましょう。

https://docs.floydhub.com/getstarted/quick_start/

GitHubからサンプルのリポジトリをダウンロードしておきます。

git clone https://github.com/floydhub/quick-start.git
cd quick-start

リポジトリの中のファイルの一覧を確認しましょう。

ls
eval.py  LICENSE  mnist_cnn.ipynb  README.md  train_and_eval.py  train.py

以降は、上記の train_and_eval.py プログラムをFloydHub上で実行してみます。

FloydHubプロジェクトを初期化します。

floyd init mnist-cnn

FloydHubでPythonプログラムを実行してみましょう。

floyd run --gpu --env tensorflow-1.3 "python train_and_eval.py"

ここでは --gpu オプションを指定してるので、GPUインスタンス上で実行されます。

FloydHubでJupyter Notebookを起動する

FloydHubのプロジェクトフォルダ上で(先のquick-startフォルダなど)、次のようにコマンドを実行します。

floyd run --mode jupyter

Creating project run. Total upload size: 198.0B
Syncing code ...
[================================] 946/946 - 00:00:00

JOB NAME
-----------------------------------
murayama333/projects/mnist-cnn/1

Setting up your instance and waiting for Jupyter notebook to become available .............

Path to jupyter notebook: https://floydlabs.com/notebooks/xxx

数秒(数十秒)でJupyterが起動します。

GPUインスタンスで起動する場合は、次のように指定します。

floyd run --gpu --mode jupyter

Jupyterを起動している間、GPUインスタンスの利用時間がカウントされるので、利用を終えたらインスタンスを停止しておきましょう。停止するときは JOB NAME(floyd run時のログを参照)を指定します。

floyd stop murayama333/projects/mnist-cnn/1

Reactだけ学ぶハンズオン

Reactだけ学ぶハンズオン

  1. Hello React・・・はじめてのReact
  2. Greeting・・・プロパティを学ぶ
  3. GreetingList・・・コレクションの考え方を学ぶ
  4. Echo・・・ステートを学ぶ
  5. Welcome・・・コンポジットなコンポーネントの作り方を学ぶ

昔の勉強会の資料です。内容古かったらすみません。

こっちのが見やすいかもです。

https://github.com/murayama333/react-handson

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>