【これだけ分かれば戦える】 React.jsの特徴とJavaScriptの頻出構文

はじめに

今回はReact.jsで最低限知っておくべき特徴と非常によく使う文法事項を解説します。
文法事項はただ説明するだけでなく、React.jsではどのように使われているかについても併せて紹介します。

これだけでも抑えておくと今後学習する際にスムーズに進めることができると思います。
ぜひこの機会にReact.jsの概要を掴みましょう。

目次

今回使用するJavaScript

今回の記事ではES7(ES2016)以降の文法を使用します。
特にクラスや関数の定義の仕方がそれ以前の文法と少し違うため、参考資料による違いに注意しましょう。

React.jsの特徴

ここではReact.jsの重要な要素であるComponent指向型のフレームワーク仮想DOMによる高速なレンダリングをしている点について紹介します。

Component指向型のフレームワーク

React.jsはComponent指向型のフレームワークと言われています。
Componentとは部品という意味です。
この部品を組み合わせて一つ画面を作るのがReact.jsの基本的な考え方となっています。

そもそもWebページはさまざまな部品によって構成されています。

Webページ

通常のHTMLでデザインする場合はHeader部分は<header>タグや<nav>タグを使ったり、List-itemは<li>タグや<ul>タグを使います。

React.jsではComponentを1つのJavaScriptファイルや関数、クラスとして定義します。
これにより必要なComponentを一度作ってしまえば再利用が可能になるため、効率よく開発ができます。

仮想DOMによる高速なレンダリング

DOM (Document Object Model)とはブラウザ上でページを表示する際に作られるものです。
このDOMをもとに画面を表示する(レンダリング)を行います。

通常のDOM生成からレンダリングまでの手順はHTMLファイルが変更されるたびに行われます。

output1

しかしこの場合だと新しいファイルが読み込まれるたびにすべてDOMに変換します。
そして毎回最初からこの工程を行うので時間がかかってしまいます。

特にReact.jsのようなComponent指向型フレームワークでは画面上で変更される部分は一部なので、そこだけ表示を変更する方が効率的です。

そこでReact.jsではDOMを生成する前に仮想DOMを生成します。
仮想DOMが生成された時点で新しい仮想DOMと古い仮想DOMと比較を行いその差分だけDOMを書き換えます。

output2

そのためすべてのDOMを作り直すよりも高速で画面を表示することができます。
この仕組みがReactでは非常に重要です。

React.jsでよく使う文法

ここからはReact.jsで非常によく使うJavaScriptの文法について紹介します。
React.jsでは実際にどう使うのかも例示するので実際につかうイメージが身につくと良いと思います。

どれも重要かつ頻出なのでこの際にまとめて覚えましょう。

importとexport

React.jsではさまざまなライブラリーやモジュールをインポートします。
その際には以下のように行います。

// import Module名 from Moduleのパス
import React from 'react'; // React.jsではファイルごとに必須
import { Route, Switch } from "react-router-dom"; // インストール済みのパッケージはそのまま記述可能

import ImportedContainer from "./containers/ImportedContainer"; // 自分で作成したものは相対パスを使用

npmでプロジェクトディレクトリにインストールしたものはimport React from 'react';のようにインポートします。
自分で作成したモジュール名はインポートする際には好きな名前をつけることができます。

また他のファイルからインポートするためには、インポートするファイルをエクスポートする必要があります。

import React, { Component } from "react";
import ImportedContainer from "./containers/ImportedContainer";

class App extends Component {
  render() {
    return (
      <div>
                <ImportedContainer />
      </div>
    );
  }
};

// export default class名 or function名
export default App;

エクスポートしなければ他のファイルからインポートできないので慣れないうちは注意しましょう。

constとlet

変数を定義する際にconstもしくはletを宣言します。

const Person1 = 'Fuginami';
let Person2 = 'Hashimoto';

同じように思えるかもしれませんが、これらには使い分けが存在します。
constで宣言した変数は再代入ができません。

const Person1 = 'Fuginami';

Person1 = 'Tyousyuu'; // Error
console.log(Person1);

変数を定義する際は再代入するものなどはletで定義し、それ以外はconstで定義するのが一般的です。
React.jsでも基本的にはconstを使い、状況に応じて変数が変わる可能性があるものだけletを使います。

map()

map()は配列に対して使用するメソッドです。
配列の各要素1つずつに対して関数(コールバック関数)を適用し、新しい配列を作ることができます。

const Array = [1, 3, 5, 7, 9]

const doubleNumber = (x) => {
    return x*2
}
doubleArray = Array.map(doubleNumber)
// [2, 6, 10, 14, 18]

また、別で関数を定義せずに直接map()に関数をいれることも可能です。
この方がコードを短く書けるので使用頻度は多いかもしれません。

const Array = [1, 3, 5, 7, 9]

doubleArray = Array.map(num => num*100) // Arrayの1つ1つの要素がnumに代入されて関数が適用
// [100, 300, 500, 700, 900]

map()はReact.jsでは非常によく使います。
例えば、何らかのAPIを使ってデータを取ってきた(フェッチ)際にそのデータをComponentに渡して出力したいケースに使用します。

import React, { Component } from "react";
import Order from "./components/Order";

class Orders extends Component {
  state = {
    orders: []
  };

  componentDidMount() {
        // ここでAPIからデータを受けとってstateのordersに入れておく
    ...
  }

  render() {
    return (
      <div>
        <!-- 先程APIから受けとってordersに入れて要素をOrderというComponentに代入する-->
        {this.state.orders.map(order => (
          <Order
            id={order.id}
                        item={order.items} // ここで割り当てる
          />
        ))}
      </div>
    );
  }
}

配列を取り出してComponentに入れる作業をたった数行で行えるので非常に重宝します。

三項演算子

三項演算子はif文を省略して書く記法です。
通常、if文で条件式がtrue時とfalse時を分岐させて記述します。

const age = 22;

if (age >= 18) {
  console.log("You can ride a motorcycle.")
} else {
  console.log("You can't ride a motorcycle!!!")
}

これを三項演算子では一行で書けます。

// 条件式?条件がtrueのときに実行する処理:条件式がfalseのときに実行する処理
age >= 18 ? console.log("You can ride a motorcycle.") : console.log("You can't ride a motorcycle!!!")

これもReact.jsではよく使います。
三項演算子を使うとアプリケーションの状態に応じてHTMLに作用させるCSSを変更できます。

例えばModalを作りたい場合は以下のようにCSSを割り当てます。

<Modal style={{
  // transform: 表示位置の移動
    transform: this.state.show ? "translateY(0)" : "translateY(-100vh)", 
  // opacity: 透明度
    opacity: this.state.show ? "1" : "0" 
  }} />

アプリケーションに何らかの変化(ボタンを押すなど)が起きてthis.state.showがtrueになった場合はModalのCSSにtransform: translateY(0);opacity: 1になり画面に表示させます。

falseのときはtransform: translateY(-100vh);opacity: 0なので画面外に透明な状態で隠れていることになります。

modal

このようにアプリの状態に応じた処理の変更がする際によく使用されます。

switch文

三項演算子の場合はtrueかfalseの場合の処理しかできません。
もっと条件分岐させたい場合はswtich文を使います。

switch(条件式) {
  case 値1:
    「条件式=値1」である場合に実行される命令;
    break;
  case 値2:
    「条件式=値2」である場合に実行される命令;
    break;
  ...
  case 値n:
    「条件式=値n」である場合に実行される命令;
    break;
  default:
    条件式の値がどの条件にも合致しない場合に実行される命令;
}

具体的には以下のように使います。

const input = 'text'

switch(input) {
  case 'text':
    console.log('this is text');
  case 'number':
    console.log('this is number');
    break;
  default:
    console.log('What is this?');
}

React.jsではフォーム画面で入力のタイプ(数字、テキスト、E-mialなど)によって違う処理をしたい場合などに使用します。

三項演算子だけではカバーしきれないものはswitch文を使うと良いでしょう。

bind()

bind()は関数に設定を追加して新しい関数を生成する関数です。
なかなか分かりづらいので、最初に例を示します。

class Person {
  // プロパティ:クラス内の情報. constructor()はプロパティを定義するための関数
  constructor() {
   this.name = 'Yui' 
  }

  saySomething = () => {
    console.log('Hi, I am ' + this.name)
  }
}

class Dog {
  constructor() {
   this.name = 'Pochi' 
  }
}

const yui = new Person()
const pochi = new Dog()

// bind()は関数を返しているので最後の実行の()は忘れずに
yui.saySomething.bind(pochi)() // Hi, I am Pochi

const pochi = new Dog()で定義したDogクラスのプロパティをbind()を用いてPersonクラスに紐付けています。
それによってPersonのプロパティでname='Yui'と定義したものが'Pochi' に上書きされました。
このようにbind()は関数と関数をbind(紐付け)することができます。

React.jsではイベントハンドラを定義する際に使用します。
公式ドキュメントにはこのように書かれています。

JSX のコールバックにおける this の意味に注意しなければなりません。JavaScript では、クラスのメソッドはデフォルトではバインドされません。this.handleClick へのバインドを忘れて onClick に渡した場合、実際に関数が呼ばれた時に thisundefined となってしまいます。

イベント処理:https://ja.reactjs.org/docs/handling-events.html

つまり何らかの関数をクラス型のコンポーネントで使用する際にはconctructorでthis.handleClick = this.handleClick.bind(this);のようにする必要があります。

class LoggingButton extends React.Component {
  constructor(props) {
    super(props);
    // ここでthisをbind
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

ただし、毎回constructor()bind()を使ってthisにイベントハンドラを紐付けるのは面倒です。
React.jsではbind()を使わなくて済む解決策があります。

1つはアロー関数を使う方法です。

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    return (
      // eventを渡す必要あり
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

この他にも回避する方法はさまざまなものがあります。
興味があれば、以下の記事を参考にしてみてください。

Reactをes6で使う場合のbindの問題:
https://qiita.com/cubdesign/items/ee8bff7073ebe1979936

まとめ

お疲れさまでした。
React.jsの特徴と文法は理解できたでしょうか。
特に一番最後のbind()は少しわかりにくかったかもしれません。

ここまで理解できればReact.jsを学習するための素地はできています。
まったく何もわからない状態から始めるよりもスムーズに学習できるはずです。

今回の記事が読んでくれた方の学習の糧になれば幸いです。

React.jsに関する他の記事を見る↓↓

https://code-ship-blog.wemotion.co.jp/technology/%e3%80%90react%e3%80%91%e3%82%a2%e3%83%97%e3%83%aa%e9%96%8b%e7%99%ba%e3%82%aa%e3%82%b9%e3%82%b9%e3%83%a1%e8%a8%98%e4%ba%8b%e3%81%be%e3%81%a8%e3%82%81%ef%bc%81%e8%a8%80%e8%aa%9e%e3%83%bbfw%e3%81%ae/

参考文献・URL

VirtualDOMの仕事ってなに?(Reactの表示速度がはやい理由)
https://qiita.com/risagon/items/019942c60e9c3e6c05a5

(初心者向け) JavaScript のクラス (ES6 対応)
https://qiita.com/tadnakam/items/ae8e0e95107e1427983f

React公式 イベント処理
https://ja.reactjs.org/docs/handling-events.html


おすすめ記事

https://code-ship-blog.wemotion.co.jp/technology/%e3%80%90web%e3%83%9a%e3%83%bc%e3%82%b8%e3%83%87%e3%82%b6%e3%82%a4%e3%83%b3%e5%85%a5%e9%96%80%e3%80%91-jquery%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%88%e3%81%86/
https://code-ship-blog.wemotion.co.jp/technology/%e3%80%90%e7%b0%a1%e5%8d%98%e3%81%ab%e3%83%9a%e3%83%bc%e3%82%b8%e3%82%92%e3%83%87%e3%82%b6%e3%82%a4%e3%83%b3%e3%81%a7%e3%81%8d%e3%82%8b%e3%80%91bootstrap%e3%81%a3%e3%81%a6%e4%bd%95%e3%81%a0%e3%82%8d/
https://code-ship-blog.wemotion.co.jp/technology/react%e3%81%ae%e9%96%8b%e7%99%ba%e7%92%b0%e5%a2%83%e3%82%92docker%e3%81%a7%e6%95%b4%e3%81%88%e3%82%88%e3%81%86/