9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FORKAdvent Calendar 2020

Day 17

Reactアプリケーション開発入門

Last updated at Posted at 2020-12-16

■create-react-appのインストール&Hello Worldの表示

create-react-appはFacebookが提供しているCLIツールです。
環境構築の手間をスキップして学習に集中できます。

// create-react-appのインストール
yarn global add create-react-app

// Reactアプリケーションの作成
create-react-app hello-world

// hello-worldに移動
cd hello-world

// 開発開始
yarn start

7b695480-013f-11eb-82ee-a6989fc53549.png

ファイル構造はこんなかんじです。
7b695480-013f-11eb-9223-07d42cd3a344.png

Hello Worldを表示するにはsrc/App.js内をこのように書き換えます。

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code>and save to reload {/* この行をHello Worldに書き換える */}
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

これでHello Worldが表示されました。
7c01eb00-013f-11eb-8f31-3b24ac4893e5.png

ちなみにこのreturn()内の部分はぱっと見HTMLに見えますが、実際はJSXというものになっています。
詳細は公式をご確認ください。( https://ja.reactjs.org/docs/introducing-jsx.html )

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  //このreturnの中がJSX
  return ( 
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Hello World
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

■コンポーネントについて

Reactのコンポーネントには「関数コンポーネント」と「クラスコンポーネント」の二種類があります。

<関数コンポーネント>

実は先ほどのHello Worldを表示した時のApp.jsが既に関数コンポーネントの形になっていました。

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Hello World
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

わかりやすく余計な部分を省いた形が下記になります。
※ちなみにですが、JSXが内部的にReactを使用しているため「import React from 'react';」の記述を無くすとエラーになります。

import React from 'react';

function FunctionComponentA() {
  return (
    <div className="function-component_A">
      function-component_Aです
    </div>
  );
}

export default FunctionComponentA;

このようにsrc/index.jsに追加することで反映されます。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import FunctionComponentA from './FunctionComponentA' //ここに追加
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <FunctionComponentA /> {/* ここに追加 */}
  </React.StrictMode>,
  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();

7c9a8180-013f-11eb-8449-abdbaf2c3e57.png

このようにアロー関数の形で定義することもできます。

import React from 'react';

const FunctionComponentB = () => {
  return (
    <div className="function-component_B">
      function-component_Bです
    </div>
  );
}

export default FunctionComponentB;

<クラスコンポーネント>

クラスコンポーネントはこのように定義します。

import React, { Component } from 'react';

class ClassComponent extends Component {
  render() {
    return (
      <div className="class-component">
        ClassComponentです
      </div>
    )
  }
}

export default ClassComponent;

Componentを継承したクラスとして定義します。

<関数コンポーネントとクラスコンポーネントそれぞれの特徴>

関数コンポーネント
・簡潔に書けるので基本はこちらが望ましい。
・状態管理によるレンダー制御ができない。

クラスコンポーネント
・状態管理によるレンダー制御が可能。
・ローカルstateやライフサイクルメソッドが利用可能。

■props

こちらが見本になります。

import React from 'react';

const Parent = () => {
  return (
    <div>
      <strong>表示されるとこうなります</strong>
      <Child name={"ポール・マッカートニー"} instrument={"ベース"} />
      <Child name={"ジョン・レノン"} instrument={"ギター"} />
      <Child name={"ジョージ・ハリスン"} instrument={"ギター"} />
      <Child name={"リンゴ・スター"} instrument={"ドラム"} />
    </div>
  )
}

const Child = (props) => {
  return (
    <div>僕は{props.name}です担当は{props.instrument}です</div>
  )
}

export default Parent;

7dcbae80-013f-11eb-8c85-0e24cc520e73.png

Child(子コポーネント)をParent(親コンポーネント)で利用する際に属性のような形でpropsを渡すことができます。
渡ったpropsはChild側で受け取り、利用するという流れになります。

データを配列で一括に渡したいと言う時には、「map」を利用することで実現可能です。
下記キャプチャでは、配列ビートルズをmapで展開しています。

import React from 'react';

const Parent2 = () => {
  const beatles = [
    {
      name: "ポール・マッカートニー",
      instrument: "ベース"
    },
    {
      name: "ジョン・レノン",
      instrument: "ギター"
    },
    {
      name: "ジョージ・ハリスン",
      instrument: "ギター"
    },
    {
      name: "リンゴ・スター",
      instrument: "ドラム"
    }
  ]
  return (
    <div>
      <strong>表示されるとこうなります(map)</strong>
      {
        beatles.map((beatlesMember, index) => {
          return <Child name={beatlesMember.name} instrument={beatlesMember.instrument} key={index} />
        })
      }
    </div>
  )
}

const Child = (props) => {
  return (
    <div>僕は{props.name}です担当は{props.instrument}です</div>
  )
}

export default Parent2;

■prop-types(型チェック)

こちらが見本になります。

import React from 'react';
import PropTypes from 'prop-types' //これをimportします。

const Parent = () => {
  return (
    <div>
      <strong>表示されるとこうなります</strong>
      <Child name={"ポール・マッカートニー"} year={1942} guitar={true} />
      <Child name={"ジョン・レノン"} year={1940} guitar={true} />
      <Child name={"ジョージ・ハリスン"} year={1943} guitar={true} />
      <Child name={"リンゴ・スター"} year={1940} guitar={false} />
    </div>
  )
}

const Child = (props) => {
  return (
  <div>僕は{props.name}です{props.year}年生まれです{props.guitar ? 'ギターを弾けます。' : 'ギターは弾けません。'}</div>
  )
}

//ここでpropsに対しての型定義を行っています。
Child.propTypes = {
  name: PropTypes.string,
  year: PropTypes.number,
  guitar: PropTypes.bool
}

export default Parent;

prop-typesを導入する手順としては、

  1. PropTypesをimportする。
  2. コンポーネントのpropsに対して型定義を行う。
    になります。

●動作確認
「name="リンゴ・スター"」の部分のyearとguitarの値を文字列に変えてみます。

import React from 'react';
import PropTypes from 'prop-types' //これをimportします。

const Parent = () => {
  return (
    <div>
      <strong>表示されるとこうなります</strong>
      <Child name={"ポール・マッカートニー"} year={1942} guitar={true} />
      <Child name={"ジョン・レノン"} year={1940} guitar={true} />
      <Child name={"ジョージ・ハリスン"} year={1943} guitar={true} />
      <Child name={"リンゴ・スター"} year={"1940"} guitar={"false"} /> {/* ここの値を間違ったもの(文字列)に変更 */}
    </div>
  )
}

const Child = (props) => {
  return (
  <div>僕は{props.name}です{props.year}年生まれです{props.guitar ? 'ギターを弾けます。' : 'ギターは弾けません。'}</div>
  )
}

//ここでpropsに対しての型定義を行っています。
Child.propTypes = {
  name: PropTypes.string,
  year: PropTypes.number,
  guitar: PropTypes.bool
}

export default Parent;

7efcdb80-013f-11eb-8bb6-08f6fd378bcd.png

無事にエラーが吐き出されました。

■state

こちらが見本になります。
countというstateを持ったCounterコンポーネントを作成しました。

import React, { Component } from 'react';

class Counter extends Component {
  // 状態を持たせるための処理
  constructor(props) { // コンポーネントの初期化時に呼び出される
    super(props)
    // this.stateでstateにアクセスできる。
    this.state = { count: 0 }
  }

  countUp = () => {
    this.setState({ count: this.state.count + 1 }) // stateを変更する時は必ずsetState()を使用する。
  }

  countDown = () => {
    this.setState({ count: this.state.count - 1 }) // stateを変更する時は必ずsetState()を使用する。
  }

  render() {
    return (
      <div className="counter">
        <div>count:{ this.state.count }</div>
        <button onClick={this.countUp}>+1</button>
        <button onClick={this.countDown}>-1</button>
      </div>
    )
  }
}

export default Counter;

7f957200-013f-11eb-9bd5-315fd9447874.png

以下、ポイントになります。

・レンダー制御が必要なのでクラスコンポーネントで作成した。
・stateの値を変更する時はsetState()を必ず使用する。
・this.stateでstateにアクセスする。

:christmas_tree: FORK Advent Calendar 2020
:arrow_left: 16日目 Full Static Generationを試す @AsaToBan
:arrow_right: 18日目 Reactで神経衰弱を作ってみた @ktn

9
3
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
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?