😊

今さら訊けないReactの基本メモ

に公開

やること

モダンなフロントエンド開発で大事そうなReactの基本をまとめておく

参考文献

https://ja.react.dev/learn

コンポーネント

コンポーネントとは何か

コンポーネントはUIの再利用可能な構成部品であり、マークアップ、CSS、JavaScriptを一つにまとめたものです。例えばボタン、フォーム、ダイアログ、アバターなど、画面上のあらゆるUI要素をコンポーネントとして定義できます。

コンポーネントの定義方法

Reactのコンポーネントは基本的にJavaScript関数として定義します。ただし、通常の関数とは異なり、名前は常に大文字で始める(例:Profile、Button、Navigation)、JSXマークアップをreturnするといった特徴があります。

function Greeting() {
  return (
    <h1>こんにちは、Reactの世界へ!</h1>
  );
}

export default Greeting;

Propsの使用方法

Reactコンポーネントは互いにやりとりをする際に「props」というものを使います。propsは親コンポーネントから子コンポーネントに情報を渡すための仕組みです。HTML属性に似ていますが、オブジェクト、配列、関数など、あらゆるJavaScriptの値を渡すことができます。
例えば、次のようにして親コンポーネントでpropsを渡し、子コンポーネントでは、関数の引数としてpropsを受け取ります。

// 親コンポーネント
function Profile() {
  return (
    <Avatar 
      person={{ name: 'micky', imageId: 'image_01' }}
      size={100}
    />
  );
}

// 子コンポーネント
function Avatar({ person, size }) {
  // ここでpersonオブジェクトとsizeを使用
  return (
    <img
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

State(状態)の管理

コンポーネントがユーザー操作に反応して変化する場合、useStateフックを使用して状態(state)を管理します。stateはコンポーネントのメモリのようなもので、ユーザー操作などによって変化する値を保持します。

import { useState } from 'react';

function Counter() {
  // count: 現在の状態値
  // setCount: 状態を更新するための関数
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        増加
      </button>
    </div>
  );
}

イベント処理

イベント処理は、ユーザーのインタラクション(クリック、入力、ホバーなど)に応答するための仕組みです。Reactでは、JSXにイベントハンドラを追加することで、様々なユーザーインタラクションに対応できます。イベントハンドラとは、特定のイベントが発生した時に実行される関数のことです。

イベントハンドラの記述方法

イベントハンドラは主に以下の2種類の方法があるようです。

// コンポネント内で関数を定義して渡す
function Button() {
  function handleClick() {
    alert('クリックされました!');
  }
  
  return <button onClick={handleClick}>クリックしてください</button>;
}

// インラインで関数を定義する
function Button() {
  return <button onClick={() => alert('クリックされました!')}>クリックしてください</button>;
}

イベントハンドラとして関数を渡す際の注意点としては、関数を「渡す」のであって、「呼び出す」のではないということです。
正: <button onClick={handleClick}>
誤: <button onClick={handleClick()}>

後者の書き方だと、レンダリング時に関数が即座に実行されてしまい、クリックイベント時には実行されません。

イベント伝播

Reactでは、DOMと同様にイベントが「バブリング」または「伝播」します。つまり、子要素でイベントが発生すると、それは親要素にも伝わります。なので、イベント伝播を停止したい場合は、イベントオブジェクトのstopPropagation()メソッドを使用します

<div onClick={handleParentClick}>
  親要素
  <button onClick={handleChildClick}>子要素</button>
</div>

function handleChildClick(e) {
  e.stopPropagation();
  // 処理...
}

デフォルト動作の防止

フォーム送信などの一部のイベントには、ブラウザのデフォルト動作があります。これを防止するには、イベントオブジェクトのpreventDefault()メソッドを使用します。

function handleSubmit(e) {
  e.preventDefault();
  // フォーム処理...
}

再レンダリング

再レンダリングは、UIを最新の状態に保つための基本的なメカニズムで、以下の場合に再レンダリングが発生します。
・コンポーネントの初回レンダリング時
・コンポーネント自身の状態(state)が更新されたとき
・親コンポーネントが再レンダリングされたとき
・コンポーネントがpropsを受け取り、その値が変更されたとき

以下は「カウントアップ」ボタンをクリックするたびに setCount が呼び出され、コンポーネントが再レンダリングされる例です。コード内でReactは前回のレンダリング結果と今回の結果を比較し、実際に変更があった部分(この場合は数字の表示部分)だけを更新します。

function Counter() {
  const [count, setCount] = useState(0);
  
  console.log('Counter コンポーネントがレンダリングされました');
  
  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        カウントアップ
      </button>
    </div>
  );
}

useEffectと副作用

useEffectはReactにおける副作用を処理するためのフックです。副作用とは、レンダリング以外のタスクのことで、データフェッチングやDOMの直接操作を指します。

useEffectの基本構文

useEffectは以下のように依存配列によって挙動が異なるので、理解しておく必要があります。

// 依存配列がない場合、すべての再レンダリング後に実行
useEffect(() => {
  console.log('毎回の再レンダリング後に実行');
}); // 依存配列を省略

// 空の依存配列の場合、マウント時一度だけ実行され、アンマウント時クリーンアップ関数が実行
useEffect(() => {
  console.log('マウント時のみ実行');
  
  return () => {
    console.log('アンマウント時のみ実行');
  };
}, []); // 空の依存配列

// 依存値を含む配列の場合、初回レンダリング時と指定した依存値countが変更されたときのみ実行
useEffect(() => {
  console.log(`count が変更されました: ${count}`);
  
  return () => {
    console.log('count変更前またはアンマウント時に実行');
  };
}, [count]); // count を依存値として指定

イベントリスナーの具体例

この例では初期状態として、現在のウィンドウの innerWidth と innerHeight を取得してオブジェクトとして設定し、useState フックを使用して、ウィンドウのサイズを保持する状態変数 windowSize を作成しています。その後、useEffect でイベントリスナーを設定し、コンポーネントのレンダリングを行うという流れです。

// 1. 状態(State)の設定
function WindowSizeTracker() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight
  });

  // 2. useEffect によるイベントリスナーの設定
  useEffect(() => {
    // ハンドラー関数の定義
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight
      });
    }
    // イベントリスナーの追加
    window.addEventListener('resize', handleResize);
    // クリーンアップでイベントリスナーを削除
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // マウント時にのみ設定

  // 3. コンポーネントのレンダリング
  return (
    <div>
      <p>幅: {windowSize.width}px</p>
      <p>高さ: {windowSize.height}px</p>
    </div>
  );
}

コメントなど

Reactの基本をざっくりまとめてみました。それぞれの概念はこういうもんかとわかったものの、もう少し触ってみないとよくわからんという感じですね。あと最後の方でuseEffectについて書きましたが、なるべく使わない方がいいらしい...この辺の話も次回以降記事にしていこうと思います。

ヘッドウォータース

Discussion