Reactでは、Reactコンポーネントの記述方法が2つあります。

  • 関数を使用するFunction Component(関数コンポーネント)
  • クラスを使用するClass Component(クラスコンポーネント)

2019年にReact 16.8に「Hooks」が導入され、関数コンポーネントの使用が増加しています。

今回は、なぜ関数コンポーネントの使用が増加しているのか?関数コンポーネントとクラスコンポーネントの違いは?について解説します。

Componentとは

Componentとは、UIの一部をパーツ化して切り出すことができる機能です。

ページのUIを適度な粒度のコンポーネントに分解することで、可読性が上がり再利用性が増します。

コンポーネントは以下のように書きます。(※関数コンポーネントの例)

import React, { Component } from 'react';

class Test extends Component {
  render() {
    return <p>Hello!</p>;
  }
}

export default Test;

上記で作成したコンポーネントを使う場合は、以下のように呼び出します。

import React from 'react';
import ReactDOM from 'react-dom';
import Test from './Test';

ReactDOM.render(
  <Test/>,
  document.getElementById('root')
);

<Test/>と記述するだけで、任意のページで呼び出すことが可能です。このように、簡単に使うことができ、可読性再利用性に優れていることが分かります。

Class componentとFunction componentの違い

では具体的にClass componentとFunctional componentの違いを解説します。結論、大きな違いは「コード量」です。

具体的にコード量がどのように違うのかコンポーネントを主に使用する以下3つから違いを見ていきます。

  • JSX
  • Props
  • State

JSX

JSXとは、React要素をHTML形式に似た構文で書くことができる、JavaScriptを拡張したものです。

JSXを使うことによって、簡便にReactを扱うことが可能です。では、実際にJSXを利用する各コンポーネントでの記述方法を確認しましょう。

関数コンポーネントの記述

関数コンポーネントは、JSXを返すプレーンなJavaScript関数なので、JavaScriptの標準的な関数と同じような記述が可能です。

import React from "react";
 
const FunctionComponent = () => {
 return <h1>Hello, React</h1>;
};

クラスコンポーネントの記述

クラスコンポーネントは、React.Componentを拡張するJavaScriptクラスです。ES6に沿った記述をします。

import React, { Component } from "react";

class ClassComponent extends Component {
 render() {
   return <h1>Hello, React</h1>;
 }
}

Props

Propsとは、コンポーネントに属性として設定ができる値のことを指します。簡単に説明すると、親コンポーネントから子コンポーネントへ値を渡すための仕組みのことです。

Propsは一度セットすると値の変更ができません

では、実際にPropsを利用した各コンポーネントでの記述方法を確認しましょう。

以下のコード例では「TARO」という名前のpropsを受け渡しています。

関数コンポーネントの記述

関数コンポーネントでは、引数としてPropsの引き渡しが可能です。

<FunctionComponent name="TARO" />

const FunctionComponent = (props) => {
 return <h1>Hello, {props.name}</h1>;
};

「FunctionComponent」を呼び出した際に、引数からpropsを受け取っています。

非構造化を使用した記述だと以下のようになります。

<FunctionComponent name="TARO" />

const FunctionComponent = ({props}) => {
 return <h1>Hello, {name}</h1>;
};

非構造化の記述方法だと、直接props名を指定して値を受け取ることが可能です。

クラスコンポーネントの記述

<Component name="TARO" />

class ClassComponent extends React.Component {
  render() {
    const { name } = this.props;
    return <h1>Hello, { name }</h1>;
 }
}

クラスコンポーネントの場合、thisを使用してpropsを参照する必要があります。

State

Stateとは、各コンポーネントごとにコンポーネント内の状態を管理する仕組みのことです。コンポーネント利用時に値を設定することができ、Stateは後から値の変更が可能です。

最近まで、クラスコンポーネントのみでstateは使用可能でしたが、React 16.8でReact Hook useStateが登場してから関数コンポーネントでも記述が可能になりました。

では、実際にStateを利用した各コンポーネントでの記述方法を確認しましょう。

以下のコード例では「クリックするとカウント数が増えるカウンター」を例にstateの記述方法を解説します。

関数コンポーネントの記述

今回のState名は「count 」です。「button onClick」されたら「count」のStateが増えていく仕組みになっています。

const FunctionComponent = () => {
 const [count, setCount] = React.useState(0);

 return (
   <div>
     <p>count: {count}</p>
     <button onClick={() => setCount(count + 1)}>Click</button>
   </div>
 );
};

関数コンポーネントでstate変数を使用するには、初期状態の引数を取るuseStateフックを使用する必要があります。

今回は、Stateのcountには初期状態として0を初期セットをしています。

クラスコンポーネントの記述

class ClassComponent extends React.Component {
 constructor(props) {
   super(props);
   this.state = {
     count: 0
   };
 }

 render() {
   return (
     <div>
       <p>count: {this.state.count} times</p>
       <button onClick={() => this.setState({ count: this.state.count + 1 })}>
         Click
       </button>
     </div>
   );
 }

クラスコンポーネントでのstateを処理する場合、関数コンポーネントと概念は同じですが構文が異なります。

関数コンポーネントを使用するメリット

「JSX・Props・State」の記述方法を比較してわかったように、関数コンポーネントを使用する大きなメリットは構文の短さです。

今回のコード例は、記述量が少ないため、あまり魅力的に感じなかったかもしれませんが、1000行以上〜などになると、構文の短さや可読性の高さが明確に現れてきます。

以前は「State・Lifecycle」がクラスコンポーネントでしか使用することのできない機能でした。しかし、゙React Hooks の登場により、関数コンポーネントでも扱うことが可能となりました。

そのため、関数コンポーネントを使用した記述方法がメジャーになってきています。

参考資料

関数コンポーネントとクラスコンポーネントを更に詳しく知りたい方は、公式ドキュメントから確認可能です。

React公式チュートリアル

まとめ

今回は、関数コンポーネントとクラスコンポーネントの違いについて解説しました。

全体的に関数コンポーネントを推している内容となっていますが、クラスコンポーネントにもメリットは存在します。

しかし、構文の短さ・可読性の高さを考慮すると関数コンポーネントがメジャーになりつつある理由に納得します。

また、ReactチームがReact Hooksの開発・サポートを重点的に行っていることもあり、関数コンポーネントを使う機会が、今後一層増すと考えられます。