LoginSignup
0
0

React入門

Posted at

はじめに

Reactは、Facebookが開発したJavaScriptのライブラリで、ユーザーインターフェイス(UI)の構築に使用されます。Reactは、コンポーネントベースのアプローチを採用しており、再利用可能なUIの部品を作成することができます。

Reactの主な特徴は以下の通りです。

仮想DOM(Virtual DOM):Reactは、仮想DOMを使用して効率的にUIを更新します。
仮想DOMは、実際のDOMの軽量なコピーで、変更の検出と適用を最適化します。

コンポーネントベース:Reactは、UIをコンポーネントに分割することを推奨します。コンポーネントは、独立した再利用可能な部品で、プロパティ(props)を受け取り、JSXを使ってレンダリングします。

単方向データフロー:Reactでは、データは親コンポーネントから子コンポーネントへと一方向に流れます。これにより、アプリケーションの状態管理が簡素化されます。

JSX:ReactではJSXと呼ばれる構文を使用します。JSXは、JavaScriptにXMLライクな記法を導入し、コンポーネントのレンダリングを宣言的に記述できます。

これらの特徴により、Reactは大規模で複雑なUIの開発に適しています。

1.コンポーネントの作成

Reactでは、UIの構成要素をコンポーネントとして定義します。コンポーネントは、関数コンポーネントとクラスコンポーネントの2種類があります。

1.1関数コンポーネント

関数コンポーネントは、propsを受け取り、JSXを返す関数です。関数コンポーネントは、状態を持たない単純なコンポーネントを作成するために使用されます。
例えば、「Hello, [名前]!」と表示するコンポーネントを作成するとします。

jsx
function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>;
}

function App() {
  return (
    <div>
      <Greeting name="Alice" />
      <Greeting name="Bob" />
    </div>
  );
}

ここでは、
Greetingコンポーネントはnameというpropを受け取っています。このpropは、コンポーネントを使用する側から渡されます。

Appコンポーネントでは、Greetingコンポーネントを2回使用しています。その際、namepropに異なる値("Alice""Bob")を渡しています。
これにより、Greetingコンポーネントは次のようにレンダリングされます。

html
<div>
  <h1>Hello, Alice!</h1>
  <h1>Hello, Bob!</h1>
</div>

1.2クラスコンポーネント

クラスコンポーネントは、React.Componentを継承したクラスです。クラスコンポーネントは、状態(state)を持つことができ、ライフサイクルメソッドを使用できます。

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

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

上記の例では、Counterというクラスコンポーネントを定義しています。constructorメソッド内で初期状態を設定し、renderメソッド内でJSXをレンダリングしています。this.stateを使って状態にアクセスし、this.setStateを使って状態を更新しています。

2.JSXの使い方

JSXは、JavaScriptの構文拡張で、HTMLライクな記法でコンポーネントのレンダリングを記述できます。JSXは、最終的にReactのcreateElement関数に変換されます。

jsx
const element = (
  <div>
    <h1>Hello, World!</h1>
    <p>This is a JSX example.</p>
  </div>
);

上記の例では、JSXを使ってdiv要素の中にh1要素とp要素を記述しています。JSXは、1つの親要素で囲む必要があります。
JSXの中では、JavaScriptの式を中括弧{}で囲むことで埋め込むことができます。

jsx
const name = "John";
const element = <h1>Hello, {name}!</h1>;

上記の例では、name変数の値をJSXの中で使用しています。

3.propsの受け渡し

propsは、コンポーネントに渡されるデータを表します。propsは、親コンポーネントから子コンポーネントへと受け渡されます。

jsx
function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>;
}

function App() {
  return (
    <div>
      <Greeting name="John" />
      <Greeting name="Jane" />
    </div>
  );
}

上記の例では、AppコンポーネントからGreetingコンポーネントにnameプロパティを渡しています。Greetingコンポーネントは、props.nameを使ってデータにアクセスしています。

4.イベントハンドリング

関数コンポーネントでイベントハンドリングを行うには、JSXの中でイベントハンドラを指定します。イベントハンドラは、ユーザーの操作に応じて呼び出される関数です。

jsx
import React from 'react';

function Button() {
  function handleClick() {
    console.log("Button clicked!");
  }

  return <button onClick={handleClick}>Click me</button>;
}

上記の例では、ButtonコンポーネントがhandleClick関数をイベントハンドラとして使用しています。ボタンがクリックされると、handleClick関数が呼び出されます。
ほかにもさまざまなイベントハンドラがあります。

イベントハンドラ 説明
onClick 要素がクリックされたときに呼び出されます
onSubmit フォームが送信されたときに呼び出されます
onChange フォームの入力値が変更されたときに呼び出されます
onMouseOver マウスポインターが要素の上に移動したときに呼び出されます
onMouseOut マウスポインターが要素の上から離れたときに呼び出されます
onKeyDown キーが押されたときに呼び出されます
onKeyUp キーが離されたときに呼び出されます

これらのイベントハンドラを使って、ユーザーの操作に応じた処理を実装できます。

5.コンディショナルレンダリング

関数コンポーネントでコンディショナルレンダリングを行うには、JSXの中で条件式を使用します。

jsx
import React from 'react';

function Greeting(props) {
  if (props.isLoggedIn) {
    return <h1>Welcome back</h1>;
  } else {
    return <h1>Please sign up</h1>;
  }
}

このGreetingコンポーネントは、ユーザーがログインしているかどうかに応じてレンダリングする要素を決定します。

propsオブジェクトからisLoggedInプロパティを受け取ります。
isLoggedIntrueの場合は、Welcome backを返します。
isLoggedInfalseの場合は、Please sign upを返します。

つまり、このコンポーネントは、ログイン状態に応じて適切なメッセージを表示するための簡単な条件分岐ロジックを持っているのです。
親コンポーネントがisLoggedInの値を適切に設定すれば、このコンポーネントは正しい挨拶メッセージを表示することができます。

jsx
import React from 'react';

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>
      {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

function App() {
  const numbers = [1, 2, 3, 4, 5];
  return (
    <NumberList numbers={numbers} />
  );
}

NumberList コンポーネント
props オブジェクトから numbers プロパティを受け取ります。
numbers 配列の各要素に対して map() 関数を使い、listItems という配列を生成します。
map() 関数の中で、各要素に対して <li> 要素を作成しています。
key プロパティには、各要素の一意の識別子として number.toString() を設定しています。これは React が DOM の効率的な更新を行うために重要です。
・最終的に <ul> 要素の中に listItems 配列をレンダリングしています。

App コンポーネント
numbers という配列を定義しています。
<NumberList> コンポーネントを呼び出し、numbers 配列を numbers プロパティとして渡しています。

レンダリングの流れは以下のようになります。
App コンポーネントがレンダリングされると、numbers 配列が定義されます。
<NumberList> コンポーネントがレンダリングされ、numbers プロパティに [1, 2, 3, 4, 5] が渡されます。
NumberListコンポーネントの map() 関数が呼ばれ、listItems配列が生成されます。
listItems配列の各要素が <li> 要素としてレンダリングされ、<ul> 要素の中に表示されます。

このようにして、React の関数コンポーネントを使って配列からリストをレンダリングする基本的な例が実装されています。key プロパティの設定は、Reactが効率的にリストの更新を行うために重要な部分です。

7.Hooks

Hooksは、関数コンポーネントに状態や副作用を追加するための機能です。
useStateuseEffectフックとuseContextフックについて説明します。

7.1useState

useStateフックは、関数コンポーネントに状態を追加するために使用します。

jsx
import React, { useState } from 'react';

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

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

const [count, setCount] = useState(0); という行で、初期値を 0 としたステート変数 count と、それを更新するための関数 setCount を定義しています。
<p>Count: {count}</p> により、現在のカウンターの値を表示しています。
<button onClick={() => setCount(count + 1)}>Increment</button> により、ボタンをクリックすると setCount 関数を呼び出し、count の値を 1 増やしています。

具体的な流れは以下の通りです。

1.コンポーネントがレンダリングされると、useState(0) により初期の count 値が 0 に設定されます。
2.<p>Count: {count}</p> によって、現在の count 値が 0 と表示されます。
3.ユーザーがボタンをクリックすると、onClick イベントハンドラが発火します。
4.ハンドラ内の setCount(count + 1) が実行され、count の値が 1 に更新されます。
5.React は、count 値の変更を検知し、コンポーネントを再レンダリングします。
6.新しい count 値 1 が <p>Count: {count}</p> に反映されます。

このように、React の useState フックを使うことで、コンポーネント内部のステート管理が簡単に行えます。ステートの更新に応じて、コンポーネントが効率的に再レンダリングされるのが特徴です。

7.2useEffect

useEffectフックは、関数コンポーネントに副作用を追加するために使用します。
副作用とは、データの取得、サブスクリプション、タイマーなどの外部システムとのインタラクションを意味します。

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

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

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return <h1>Count: {count}</h1>;
}

このコードは、React の useEffect フックを使って、1秒ごとにカウントを増やすタイマーのサンプルです。
useEffect(() => { ... }, []); により、コンポーネントがマウントされたときに一度だけ実行されるエフェクトを定義しています。
・エフェクト内部で、setInterval() を使って 1 秒ごとに setCount を呼び出し、count の値を 1 ずつ増やしています。
・返り値の関数 () => { clearInterval(timer); } は、コンポーネントがアンマウントされたときに呼び出され、setInterval のタイマーをクリアしています。
<h1>Count: {count}</h1> により、現在の count 値を表示しています。

具体的な流れは以下の通りです。

1.コンポーネントがマウントされると、useEffect のコールバック関数が実行されます。
2.setInterval が呼び出され、1 秒ごとに setCount(prevCount => prevCount + 1) が実行されます。これにより、count 値が 1 ずつ増えていきます。
3.count 値の変更に応じて、React はコンポーネントを再レンダリングし、<h1>Count: {count}</h1> に新しい値が表示されます。
4.コンポーネントがアンマウントされると、useEffect で返された関数が呼び出され、setInterval のタイマーがクリアされます。

このように、useEffect フックを使うことで、コンポーネントのライフサイクルに合わせて副作用を管理することができます。タイマーの開始と停止を適切に行うことで、メモリリークを防ぐことができます。

7.3useContext

useContextフックは、コンテキストを使用して、コンポーネント間でデータを共有するために使用します。

jsx
import React, { useContext } from 'react';

const ThemeContext = React.createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme === 'dark' ? 'black' : 'white' }}>
      Themed Button
    </button>
  );
}

このコードは、React の useContext フックを使って、テーマの状態を管理する例です。
const ThemeContext = React.createContext('light'); により、テーマコンテキストを作成しています。
初期値は "light" に設定されています。

<ThemeContext.Provider value="dark"> により、テーマコンテキストの値を "dark" に設定しています。
<Toolbar /> コンポーネントをレンダリングしています。

<ThemedButton /> コンポーネントをレンダリングしています。

const theme = useContext(ThemeContext); により、テーマコンテキストの値を取得しています。
<button style={{ background: theme === 'dark' ? 'black' : 'white' }}> により、テーマに応じてボタンの背景色を変更しています。

具体的な流れは以下の通りです。
1.App コンポーネントがレンダリングされると、<ThemeContext.Provider> によってテーマコンテキストの値が "dark" に設定されます。
2.Toolbar コンポーネントがレンダリングされ、その子である ThemedButton コンポーネントが描画されます。
3.ThemedButton では、useContext(ThemeContext) によって "dark" のテーマ値を取得しています。
4.取得したテーマ値に応じて、ボタンの背景色が動的に変更されています。

このように、useContext フックを使うことで、コンポーネント階層の任意の場所からコンテキストの値を取得することができます。これにより、テーマの変更などのグローバルな状態管理を簡単に実現できます。

まとめ

この記事では、Reactの基礎的な概念について説明しました。
Reactは、コンポーネントベースのアプローチを採用しており、再利用可能で保守性の高いUIを構築するための強力なツールです。この記事で紹介した概念を理解することで、Reactを使ったWebアプリケーションの開発に必要な基礎知識が身につきます。
Reactの学習には時間と練習が必要ですが、公式ドキュメントやチュートリアルを参考に、実際にコードを書いて試すことが大切です。この記事を出発点として、Reactの理解を深めていってください。

0
0
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
0
0