検索
連載
モダンなフロントエンド開発者になるためのSPA超入門(終):

ReactとAngular2の使い方やコードの違いを状態管理、CSS適用、単体テストで比較する (1/3)

フロントエンド開発のアーキテクチャである「SPA(Single Page Application)」について、開発に必要となる各種フレームワークの特徴や作り方の違いなどを紹介する連載。今回は、状態管理の方法やCSSの適用、単体テストの実装方法について比較し、ReactとAngular2の違いを明らかにする。

PC用表示 関連情報
Share
Tweet
g+
LINE
Hatena

 フロントエンド開発のアーキテクチャである「SPA(Single Page Application)」について、開発に必要となる各種フレームワークの特徴や作り方の違いなどを紹介する本連載「モダンなフロントエンド開発者になるためのSPA超入門」。

 連載初回の「ゼロから学ぶ! Single Page Applicationの特徴と主なフレームワーク5選」ではSPAの特徴と取り巻く環境、フレームワークを紹介しました。前回は、そのフレームワークの中から、特に注目度が高い「React」「Angular2」を使い、簡単なTODOアプリの実装を通して、それぞれのフレームワークにおけるコンポーネントの実装方法の違いを比較しました。

 最終回である今回は、より実践的な知識として、状態管理の方法やスタイルの適用、単体テストの実装方法について比較し、ReactとAngular2の違いを明らかにします。

アプリケーションの状態管理

 クライアントでの処理量が増加するSPAアプリケーションでは、クライアントサイドでの状態(データ)管理が必須です。各フレームワークでは状態管理をするための仕組みが用意されていますので、React、Angular2それぞれにおける状態管理の方法を説明します。

 併せて、Reactによる状態管理でよく使われるフレームワークであるReduxについても紹介します。

Reactを使った状態管理

 Reactの場合、各コンポーネントで状態を保持できますが、コンポーネントの再利用性を高めるために、なるべく状態を持たない(ステートレス)コンポーネントにすることが望ましいです。そのため、原則、親のコンポーネントで状態管理を行い、子コンポーネントは状態を持たないようにします。

 本アプリケーションでは、親コンポーネントはApp.jsとして定義し、その中に複数の子コンポーネントを持つ構造となっていました。


図1 アプリケーションのコンポーネント構成イメージ

 そのため、Todoの状態などのデータについては親のApp.jsで管理し、子コンポーネントに受け渡しています。


図2 データの流れ
import React, { Component } from 'react';
//コンポーネントを読み込み
import Add from './Add';
import TodoList from './TodoList';
import '../styles/index.css';
 
class App extends Component {
  constructor(props) {
    super(props);
    // 関数のバインド
    this.addTodo = this.addTodo.bind(this);
    this.checkTodo = this.checkTodo.bind(this);	
    // stateの初期化
    this.state = {todos: []};
  }
 
  // 追加アクション
  addTodo(text) {
    const { todos } = this.state;
    this.setState(
      {
        todos: [...todos, { id: todos.length, text: text, isChecked: false }]
      }
    );
  }
 
  // チェックアクション
  checkTodo(id) {
    const todos = [...this.state.todos];
    todos.forEach((todo) => {
      if (todo.id === id) {
        todo.isChecked = !todo.isChecked;
      }
    });
    this.setState(
      { todos: todos }
    );
  }
 
  render() {
    const { todos } = this.state;
    // AddコンポーネントとTodoListコンポーネントの配置
    return (
      <div className="App">
        <Add addTodo={this.addTodo} />
        <TodoList todos={todos} checkTodo={this.checkTodo} />
      </div>
    );
  }
}
export default App;
App.js

 コンポーネントで保持する状態は、Reactが提供するstateに格納されます。Todoデータを格納するstateを用意するため、コンストラクタでstateの初期化を行います。

  constructor(props) {
    super(props);
    // 関数のバインド
    this.addTodo = this.addTodo.bind(this);
    this.checkTodo = this.checkTodo.bind(this);	
    // stateの初期化
    this.state = {todos: []};
  }
App.js(※stateの初期化部分)

 次に、stateの更新方法について説明します。

  addTodo(text) {
    const { todos } = this.state;
    this.setState(
      {
        todos: [...todos, { id: todos.length, text: text, isChecked: false}]
      }
    );
  }
App.js(※Todoデータ(state)の更新部分)

 データの追加については、Reactが提供するsetState関数を使ってstateの更新を行います。Todoを追加する処理では、stateに格納されているtodos配列に対して、新規に作成したTodoデータを追加しています。

 addTodo関数はAddコンポーネントで使用するため、propsの仕組みを使って、コンポーネントのレンダリングの際にAddコンポーネントに関数を受け渡しています。

  render() {
    const { todos } = this.state;
    // AddコンポーネントとTodoListコンポーネントの配置
    return (
      <div className="App">
        <Add addTodo={this.addTodo} />
        <TodoList todos={todos} checkTodo={this.checkTodo} />
      </div>
    );
  }
App.js(※レンダリング部分)

 Addコンポーネントでは、親から受け取ったaddTodo関数を登録ボタン(inputタグ)のonClickにセットすることで、Todoの追加処理を呼び出せるようにしています。

import React, { Component } from 'react';
import '../styles/add.css';
 
class Add extends Component {
  render() {
    const { addTodo } = this.props;
    return (
      <div className="add">
        <h2 className="title">TODOサンプルアプリケーション</h2>
        <input
          type="text"
          className="inputBox"
          placeholder="TODOを入力"
          ref={(ref) => this.inputBox = ref}
        />
        <input
          type="button"
          className="addBtn"
          value="登録"
          onClick={() => {
            addTodo(this.inputBox.value);
            this.inputBox.value = '';
          }}
        />
      </div>
    );
  }
}
 
export default Add;
Add.js
       | 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

ページトップに戻る