Facebook Twitter RSS
ホーム ウェブ企画ラボ JavaScript 初めてのReact「入門編」導入から基本まで〜TODOアプリを作ってを学ぼう!

初めてのReact「入門編」導入から基本まで〜TODOアプリを作ってを学ぼう!

この記事のタイトルとURLをコピーする
初めてのReact「入門編」導入から基本まで〜TODOアプリを作ってを学ぼう!
https://webkikaku.co.jp/blog/javascript/react-start/
facebook twitter hatena Pocket

react入門

React って何?

React とは UI を作ることに特化した JavaScript のフレームワークです。以下のようなリッチな表現の時間選択のための UI も React を使って実装されていて、 react-gradient-timepicker というライブラリ名で一般に公開されています。

react-gradient-timepicker

そのほかにも、日付選択のためのカレンダー形式の UI や Slick のようなカルーセルの UI も公開されています。React はこういった複雑な UI を作ることが得意なフレームワークです。

ただし、React を使うと、こういった UI が簡単に作れるようになるというわけではなく、JavaScript やプログラムのある程度の知識は必要になってきます。

HTML と JavaScript が合体した JSX 記法

React の特徴として JavaScript 内に HTML の様な独自の記法(JSX)を記述する点が挙げられます。

以下が JSX のサンプルの記述になります。

// RenderListコンポーネントの作成
const RenderList = (props) => {
  return (<ul className="shiritori">
    {props.items.map((item) => <li>{item}</li>)}
  </ul>);
}

// RenderListコンポーネントの利用
const items = ['コアラ', 'ラッパ', 'パリ', 'りんご'];
<RenderList items={items} />

上記の RenderList コンポーネントは単純に配列の値をリスト表示する簡単なコンポーネントです。<ul> など HTML よく見かける記述がありますが、その中に変数や関数の計算結果を出力するために {} を記述します。

この様に HTML と JavaScript が渾然一体となっているのが React の特徴の一つです。

JavaScript と HTML の距離が近いことによって JSON などのデータを HTML に反映させたりすることがとても容易です。JSX の記法を避け、普通の JavaScript で React を使うこともできます。

その場合以下の様な記述になります。

const e = React.createElement;

ReactDOM.render(
  e("ul", { className: 'shiritori' }, 
    e("li", null, 'コアラ'), 
    e("li", null, 'ラッパ'), 
    e("li", null, 'パリ'), 
    e("li", null, 'リンゴ'), 
  )
);

記述量が少なければ普通の JavaScript で記述してもわかるのですが記述量が多くなってくると HTML を JavaScript で表現するのは難しくなってきます。そのため HTML の様に直感的に記述できる JSX 記法が提供されています。

HTML が自動で更新されるリアクティブなプログラミング

React のいいところはデータを更新しただけで自動で HTML が更新される仕組みにあります。例えば以下の codepen は、入力された二つの input から合計値を計算する簡単なコンポーネントの例です。

input に値を入力するとその合計値がリアルタイムに反映されているのがわかるかと思います。

必要な部分だけが更新される仮想 DOM

React の大きな特徴として、仮想 DOM という仕組みをライブラリ本体に持っている点です。

仮想 DOM は実際の DOM ではなく、React が内部的に持っている DOM の情報になります。その仮想 DOM と実際の HTML 上の DOM を比較しその差分だけが毎回 HTML 上に再適用されます。そのため画面全体が React で構成されていたとしても、必要な部分しか更新されないため非常に高速に動作します。

jQuery との違い

jQuery と React の最大の違いは HTML を自分で更新する必要があるかどうかという点です。

変数の値に応じて宣言的に JSX を記述するため、データを更新すると自動で宣言した通り、HTML が更新されます。

jQuery の addClass や ppend 、attr などほとんどのメソッドを使う機会が無くなります。jQuery の場合、データの更新作業と HTML の書き換え作業を同時に行う必要があり読み難いコードになりがちです。

Reactの書き方

React は他のライブラリと比較すると覚えることが少ないです。とてもシンプルな設計になっていてライフサイクル、JSX、state、props について理解できればスラスラコードを書ける様になるでしょう。

JSXを理解しよう

まずは一番の鬼門である JSX を理解しましょう。JSX は HTML をタグの様に記述できるのですが、HTML との違いがいくつかあるのでその違いを押さえましょう。

class ではなく、className

React では、JavaScript の文法の一つである class と区別するために HTML タグの class を className と表現します。また label タグなどに使う for 属性も JavaScript の for 文と区別するために htmlFor を代わりに使います。

<div className="sample"></div>

HTML タグに変数や数字、boolean を代入するときは {} で括る

React では、文字列以外の値(数字、boolean、変数など)を HTML タグの属性に代入する際には {} を使います。

const str = 'sample';
<div className={str} contentEditable={false}></div>

リストの表示方法

ul や ol などのリストの中にアイテムをループして表示させたい際に React ではよく以下の様な表現が用いられます。

const siritori = ['コアラ', 'ラッパ', 'パリ' 'リンゴ'];

<ul className="shiritori">
  {shiritori.map(item => <li>{item}</li>)}
</ul>

配列(Array)のメソッドである map が用いられていますが、このメソッドでは、siritori という配列を以下の様に li タグ付きの配列に変換しています。

[
  <li>{'コアラ'}<li>, 
  <li>{'ラッパ'}</li>, 
  <li>{'パンダ'}</li>, 
  <li>{'ダチョウ'}</li>, 
  <li>{'ウリ'}</li>
];

props と state を理解しよう

次に React の props と state を理解しましょう。まずは props からです。

props は外部から注入される変数です。以下のコードでは RenderList コンポーネントに文字列配列を items として渡しています。渡された items は RenderList コンポーネントが class の場合は this.props.items という形で取得することができます。

class RenderList extends React.Component {
  render() {
    const items = this.props.items;
    return (<ul className="shiritori">
      {items.map(item => <li>{item}</li>)}
    </ul>);
  }
}

ReactDOM.render(<RenderList items={['コアラ', 'ラッパ', 'パリ', 'リンゴ']} />,
document.querySelector('#app'));

RenderList コンポーネントの出力結果

<ul className="shiritori">
  <li>コアラ</li>
  <li>ラッパ</li>
  <li>パリ</li>
  <li>リンゴ</li>
</ul>

また React ではコンポーネントを関数として表現することもできます。その場合は外部から注入された値の記述の仕方が異なります。

関数で RenderList コンポーネントを作る場合

const RenderList = (props) => {
  const { items } = props;
  return (<ul className="shiritori">
    {items.map(item => <li>{item}</li>)}
  </ul>);
}

ReactDOM.render(<RenderList items={['コアラ', 'ラッパ', 'パンダ', 'ダチョウ', 'ウリ']} />,
document.querySelector('#app'));

次に state を理解しましょう。

state はそのコンポーネントが内部的に持っている状態のことです。この状態は props と違い外部から注入できません。以下のサンプルコードではラジオボタンを3つ用意して選択された項目が表示されます。

class SelectItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: ''
    };
    this.onChange.bind(this);
  }

  onChange(e) {
    this.setState({ selected: e.target.value });
  }
  
  render() {
    const { selected } = this.state;
    return(<div>
      <p>現在 {selected} が選択されています。</p>
      <label>
        <input type="radio" value="コアラ" onChange={this.onChange}/>
        コアラ
      </label>
      <label>
        <input type="radio" value="ラッパ" onChange={this.onChange} />
        ラッパ
      </label>
      <label>
        <input type="radio" value="パリ" onChange={this.onChange} />
        パリ
      </label>
    </div>);
  }
}

ReactDOM.render(<SelectedItem />, document.querySelector('#app'));

ライフサイクルを理解しよう

次は React のライフサイクルを理解しましょう。ライフサイクルとはコンポーネントが生成されてから削除されるまでの間の一連の流れのことを指します。React ではこのライフサイクル間のあるタイミングで処理を挟み込むための一連のメソッドが用意されています。

class Example extends React.Component {
  constructor(props) {
    super(props);
  }

  // コンポーネント生成時
  componentDidMount() {
  }

  // コンポーネント更新時
  componentDidUpdate() {
  }

  //コンポーネント消滅時
  componentWillUnmount() {
  }
}

React のライフサイクルを理解しやすいように以下のような図を作って見ました。

ライフサイクル

コンポーネント生成時

コンポーネントが呼ばれた際には constructor が呼ばれます。これは class の初期化メソッドで、プログラムに精通している人だとご存知だと思います。

次に getDerivedStateFromProps です。これは親コンポーネントから渡された props を計算して自身の state を導き出すためのメソッドです。

内部の state が props の値に依存する場合は getDerivedStateFromProps を使います。その後仮想DOMを更新するための render メソッドが実行され、実際にコンポーネントの DOM が生成された後、componentDidMount が実行されます。

コンポーネント更新時

内部の state が変更された時、もしくは親コンポーネントから新しい props が渡ってきた際にコンポーネントの一連の更新処理がされます。

コンポーネント生成時と同じように getDerivedStateFromProps が実行された後、コンポーネントを再描画する必要があるかどうかを判定するための shouldComponentUpdate メソッドが動きます。

もし再描画したい場合はメソッド内で true を返します。再描画したくない場合は false を返します。false が返されると、そのあとの render メソッド、componentDidUpdate メソッドは動きません。

shouldComponentUpdate メソッドが存在しない場合は render メソッドがそのまま実行されます。もし state や props が更新されてもコンポーネントを再描画したくない場合は shouldComponentUpdate を使ってパフォーマンスチューニングしてください。

render メソッド実行後、DOMが更新されたタイミングで、componentDidUpdate メソッドが実行されます。

コンポーネント消滅時

仮想 DOM からこのコンポーネントが消滅したタイミングで componentWillUnmount メソッドが実行されます。そしてその後実際の DOM からも削除されます。

Reactの導入方法

Node.js のインストール

React の概念が理解できたところで次はいよいよ React を導入してみましょう。React を使うには Node.js というツールを利用するのが便利です。

Node.js とはもともとサーバーサイドで JavaScript を動かすためのツールなのですが、昨今では gulp や Webpack などフロントエンドを便利に開発するためのツールとしても使われるようになりました。

nodejs

上記の URL から Node.js をダウンロードしていただきダウンロードしたパッケージを解凍するだけでインストールが始まります。Node.js の導入は非常に簡単です。

Create React App のインストール

Node.js のインストール後、地道に React 環境を構築するのはとても大変です。Webpack や Babel もしくは TypeScript などの知識に精通している必要があります。

Create React App はそういった難しい設定をしなくても簡単に React を導入できるツールです。より細かい設定をしたい場合は Create React App を使わずに直接 Webpack を設定した方が早い場合もありますが趣味程度に使ってみるくらいなら Create React App でも十分です。

以下3つのコマンドをターミナルに入力するだけで何も考えずに React 環境が完成してしまいます。

npx create-react-app my-app
cd my-app
npm start

以下のような画面が立ち上がれば成功です。

Create React App

my-app ディレクトリーをお好きなテキストエディターで開いていただいて、my-app/src/App.js を変更すると変更結果がブラウザーにすぐ反映されるはずです。

実践編 Todo アプリを作ろう

React の環境が整ったのでいよいよここから実践編です。React で簡単な todo アプリを作って見ましょう。完成形を codepen に投稿してみました。

折角なので codepen 上ではなく先ほど Create React App で作成した環境を利用しましょう。

Todo クラスを作ろう

まずは todo クラスを作っていきます。my-app/src/todo.js を作成してください。以下がコンポーネントの class を作る際の雛形になります。

import React, { Component } from 'react';

class Todo extends Component {

}

render メソッドを定義

次にどのように HTML を描画するかを決めるための render メソッドを作りましょう。ここでは todo 名を入力するためのテキストフィールド、入力した todo をリストに追加するためのボタンと todo 一覧を表示するためのリストを作っています。

import React, { Component } from 'react';

class Todo extends Component {

  constructor(props) {
    super(props);
    this.state = {
      todos: [],
      name: ''
    };
  }

  render() {
    const { todos } = this.state;
    
    return (<div>
      <input type="text" />
      <button>登録</button>
      <ul>
        {todos.map((todo, index) => <li key={index}>{todo}</li>)}
      </ul>
    </div>);
  }
}

todo の追加メソッドを定義

次に todo を実際にリストに追加するためのメソッドを作って見ましょう。まずはテキストフィールドに入力された値を name として state に保存しましょう。React では state を保存するために setState というメソッドを使います。実際に入力された値は e.target.value で取り出せます。

class Todo extends Component {
  ...
  onInput = (e) => {
    this.setState({
      name: e.target.value
    });
  }
  ...
  render() {
    const { todos } = this.state;
    
    return (<div>
      <input type="text" onInput={this.onInput} />
      <button>登録</button>
      <ul>
        {todos.map((todo, index) => <li key={index}>{todo}</li>)}
      </ul>
    </div>);
  }
}

次に登録ボタンをクリックした際の処理を追加します。以下のコードでは、スプレッド演算子を使って配列を新しい配列に展開し、その末尾にテキストフィールドで入力した値をセットしています。

class Todo extends Component {
  ...
  addTodo = () => {
    const { todos, name } = this.state;
    this.setState({
      todos: [...todos, name]
    });
  }
  ...
  render() {
    const { todos } = this.state;
    return (<div>
      <input type="text" onInput={this.onInput} />
      <button onClick={this.addTodo} >登録</button>
      <ul>
        {todos.map((todo, index) => <li key={index}>{todo}</li>)}
      </ul>
    </div>);
  }
}

todo の削除メソッドを定義

次に todo を削除するボタンを作りましょう。removeTodo メソッドで削除したい todo の index 番号を受け取ってその位置にある todo を除いた配列を作り、state の todos に再セットしています。

class Todo extends Component {
  ...
  removeTodo = (index) => {
    const { todos, name } = this.state;
    this.setState({
      todos: [...todos.slice(0, index), ...todos.slice(index + 1)]
    });
  }
  ...
  render() {
    const { todos } = this.state;
    return (<div>
      <input type="text" onInput={this.onInput} />
      <button onClick={this.addTodo} >登録</button>
      <ul>
        {todos.map((todo, index) => <li key={index}>
          {todo}
          <button onClick={() => { this.removeTodo(index) }}>削除</button>
        </li>)}
      </ul>
    </div>);
  }
}

完成形は以下のようなソースコードになります。他のファイルで作った todo を読み込めるように class の先頭に export default を追加しています。

import React, { Component } from 'react';

export default class Todo extends Component {

  constructor(props) {
    super(props);
    this.state = {
      todos: [],
      name: ''
    };
  }

  onInput = (e) => {
    this.setState({
      name: e.target.value
    });
  }
  
  addTodo = () => {
    const { todos, name } = this.state;
    this.setState({
      todos: [...todos, name]
    });
  }

  removeTodo = (index) => {
    const { todos, name } = this.state;
    this.setState({
      todos: [...todos.slice(0, index), ...todos.slice(index + 1)]
    });
  }

  render() {
    const { todos } = this.state;
    return (<div>
      <input type="text" onInput={this.onInput} />
      <button onClick={this.addTodo} >登録</button>
      <ul>
        {todos.map((todo, index) => <li key={index}>
          {todo}
          <button onClick={() => { this.removeTodo(index) }}>削除</button>
        </li>)}
      </ul>
    </div>);
  }
}

最後に my-app/src/index.js で先ほど作成した todo コンポーネントを読み込めば完成です。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Todo from './todo';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<Todo />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

まとめ

これまで React を始める上での基礎をお伝えしました。JSX の記法に慣れて、props, state やライフサイクルを理解すれば React で複雑なコンポーネントも作れます。

ただし React で本格的にアプリを作るのであればその周辺技術も学ぶ必要があります。

例えば複数のコンポーネントを管理するためにアプリケーション全体の state を管理するためのライブラリとして react-redux, redux などがあります。また URL ごとに表示するコンポーネントを出し分けるためのツールとして react-router があり、React をサーバーサイドでレンダリングするためのツールとして Next.js があります。

これらの周辺技術と組み合わせながら Web アプリケーションを作ることがほとんどなので、React でコンポーネントが作れるようになった後はこういった技術も勉強して行きましょう。この記事でまずは React を始める最初の一歩を踏み出していただければ幸いです。

この記事のタイトルとURLをコピーする
初めてのReact「入門編」導入から基本まで〜TODOアプリを作ってを学ぼう!
https://webkikaku.co.jp/blog/javascript/react-start/
facebook twitter hatena Pocket

東京・名古屋を中心に、中小企業に特化したホームページ制作会社。マーケットやビジネスモデルに合わせ一社一社に合わせたウェブ制作・リニューアルのご提案しています。
1000サイト以上のウェブマーケティング支援で獲得したノウハウで、リニューアル後に過去最高の成果を生み出したお取引先は多数。勘ではなくロジックに基づいたホームページ制作と柔軟な対応力で多数のお客様にご評価頂いております。

どのようなお悩みでも構いません。ホームページを有効的に活用できていないと考えているご担当者の方、まずは一度弊社にご相談くださいませ。

ご提案依頼・ご相談はこちら
公式facebook、twitterから情報を受けとる
いいね!する フォローする
前のページ
次のページ
ページトップ