LoginSignup
79
52

More than 3 years have passed since last update.

今更だけど「Function Component」 と 「Class Component」の違いをざっくり。

Last updated at Posted at 2020-04-29

Reactを勉強中にこんがらがったのでメモ

Reactのcomponentを作成する際には大きく2種類ありそれが

・Function Component
・Class Component

現在はFunction Componentを使うことを推奨されており、その理由についても調べてみました。

そもそもComponentとは?

Reactでは複雑なUIをComponentという小さな部品を組み合わせて実現することが可能
Railsやってた人なら部分テンプレートをイメージするといいかも。

適度な粒度のコンポーネントに分けることで可読性と再利用性というメリットがある。
この適度な粒度に関してはAtomic Designという概念もある。

【参考】Atomic Designを使ってReactコンポーネントを再設計した話

コンポーネントの主な登場人物

・JSX
・Props
・State

JSX

JSXはhtml埋め込めるやつというざっくりとした考えの方もいるのではないでしょうか?
(自分もそう思っていました。 )

正確にはJSXはJavaScriptに変換さています。

Babelでコンパイルするとわかりやすいです。(右が変換後)
スクリーンショット 2020-04-28 22.35.35.png

return <div>Hello React</div>

の部分が変換されている↓

return react.default.createElement("div", null, "Hello React");

見比べて見るとわかる通りJSXの方が記述量も少なく可読性も高いですね。

Props

-コンポーネントの性質を表すもので不変
-親から子に情報を渡す

以下の二つの箱をpropsを使って再利用してみます。
Yellow Black Beer Modern Father's Day Card (3).png

Box.js
//子コンポーネント

import React from 'react';

const Box = props => {
  return ( 
    <div>{props.title}</div>
  );
};
export default Box;

App.js
//親コンポーネント

import React from 'react';
import Box from './components/box'

export default App = () => {
  return (
    <Box title="Hello world" />
    <Box title="Good bye world" />
  );
};

オブジェクトスプレッド演算子を用いるとpropsを省略できる。

//子コンポーネント

import React from 'react';

const Box = ({ title }) => {
  return (
    <div>{title}</div>
  );
};
export default Box;

※css省略

State

-コンポーネントの状態を表すもので可変
-Stateを変更することで画面が更新される

ここから本題

以前まではClass Componentではstate、ライフサイクル(componentDidMountなど)が使え、
Function Componentではそれらが使えないのが違いと言われていた。

しかし、現在ではHooksが導入されたことによりFunction ComponentでもuseState、useEffectなどを使って、
Stateやライフサイクルに相当するものが使えるようになっている。

Function Componentを使うメリット

-記述が短くなる
-動作も少し早くなると言われている。(未検証)

例) 引用(React -ステートフックの利用法-

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

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}
FunctionComponent
import React, { useState } from 'react';

function Example() {
  //state関数呼び出し
  const [count, setCount] = useState(0);

  return (
    <div>
      //ClassComponentではthis.state.countで呼び出す
      <p>You clicked {count} times</p>
      //すでにcountとsetCountを受け取っているのでthisは不要
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );

useStateは関数内で使うのでかなりスッキリ書けます。

次に副作用フックを見てみましょう。
上述のコードにクリック回数を含んだカスタムのメッセージをドキュメントのタイトルに表示してみます。
例) 引用(React -副作用フックの利用法-

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

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

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

FunctionComponent
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

少しReact触った人ならuseEffectフックはcomponentDidMount、 componentDidUpdate、 componentWillUnmountがまとまったものと言うのがわかりますね。

上述だとドキュメントのタイトルをセットしているだけですが、
データを取得したり、その他何らかの命令型の API を呼び出したりすることも可能

//東京都最新コロナ感染者を取得
//自分のアプリに実装したものを少し書き換えてます。冗長なところあれば教えてください。。🙇‍♂️

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Moment from 'moment';
import 'moment/locale/ja';

const DATA ='https://raw.githubusercontent.com/tokyo-metropolitan-gov/covid19/master/data/data.json';

function covidTokyo {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    try {
      const response = await axios.get(DATA);
      setData(response.data.patients_summary.data.slice(-1)[0]);
    } catch (error) {
      console.error(error);
    }
  };

  Moment.locale('ja');
  var dt = data['日付'];

  return (
    <div>
      東京都新型コロナ新規感染者数({Moment(dt).format('MMMDo')}
      <div> 
        +{data['小計']}
      </div>
    </div>
  );
};

結論

Hooksが導入されたことでコードの記述量といい可読性といいFunction Componentを使うことが推奨されている理由がわかったと思います。
ただ、ネットで落ちている情報などはClass Componentで書かれているものが多いので、
Class ComponentとFunction Component両方の知識は付けておくのがいいのかなと。

React駆け出しなので間違っているところなどあれば教えて頂けると嬉しいです🙇‍♂️🙇‍♂️

79
52
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
79
52