【React入門】Props(プロップス)とState(ステート)の違いとは?具体的なコード例でわかりやすく解説!

react-prop

Reactを学び始めた初心者の方が、最初につまずきやすいポイントが「Props(プロップス)」「State(ステート)」の違いや使い分けです1

Reactのユーザーインターフェース(UI)は、「データの変化に応じて自動的に画面が書き換わる」という便利な仕組みを持っています3。この画面の表示を決定するデータこそが、PropsとStateなのです4

この記事では、PropsとStateの基本的な概念から、具体的なReactのコード例、そして実践的な使い分けの基準まで、初心者の方に向けてわかりやすく解説します。

1. Reactの基本:PropsとStateは「データの持ち方」が違う

react-prop-state

Reactのコンポーネントは、データを入力として受け取り、画面に表示するHTML(JSX)を出力する「関数」のようなものです3。この入力データを扱う仕組みとして、PropsとStateという2つのオブジェクトが用意されています1

この2つの違いを、プログラミングや日常の言葉で例えると次のようになります。

  • Props(プロパティ): コンポーネントの外部(親)から渡される「引数(パラメータ)」や「設定指示書」です1。コンポーネント自身では内容を書き換えることができません1
  • State(ステート): コンポーネントが内部に持っている「ローカル変数」や「自身の記憶」です1。ユーザーの操作などによって、自分自身で自由に書き換えることができます1

この「誰がデータを管理し、誰が変更できるのか」という違いを意識することが、Reactをマスターするための第一歩になります。

2. Props(プロップス)とは?「親から子へと渡す読み取り専用データ」

Propsは、親コンポーネントから子コンポーネントへと一方通行で受け渡されるデータのことです1。Reactではデータが常に上(親)から下(子)へと流れる「一方向データフロー」という厳格なルールがあります4

Propsは「読み取り専用(変更不可)」

Propsの最も重要なルールは、「受け取った子コンポーネント側で直接書き換えてはいけない」ということです1。これは、同じ入力に対しては常に同じ画面を出力するという、関数型プログラミングの「純粋関数」の考え方に基づいています3

もし子コンポーネントが勝手にPropsを書き換えてしまうと、データの出所がわからなくなり、アプリが予期せぬ挙動を起こす原因になります。データを変更したい場合は、必ず親コンポーネント側でデータを更新し、新しいPropsとして再配達してもらう必要があります9

具体的なコード例で見るPropsの使い方

Propsは、コンポーネントの見た目や表示内容を外側からカスタマイズする「設定値」として使います3

例えば、ユーザーのアバター画像を表示するコンポーネントを作ってみましょう。JavaScriptの「分割代入(Destructuring)」を使うと、Propsをすっきりと受け取ることができます8

JavaScript

// 子コンポーネント:アバター画像を表示します
function Avatar({ person, size = 100 }) {
  // personとsizeがPropsとして渡されてきます
  return (
    <img
      className=”avatar”
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

// 親コンポーネント:子コンポーネントを呼び出してデータを渡します
export default function Profile() {
  return (
    <Avatar
      person={{ name: ‘サマーズ・ハシ’, imageId: ‘YfeOqp2’ }}
      size={100}
    />
  );
}

このコード例では、Avatarコンポーネントは親であるProfileからpersonというオブジェクトと、sizeという数値を受け取り、それに基づいて画像をレンダリングしています8。sizeにはデフォルト値(100)が指定されているため、親から指定がない場合でも安全に動作します8

便利なPropsの受け渡しテクニック

  1. スプレッド構文(…)での一括伝達: 親から受け取ったPropsをそのままさらに奥の子コンポーネントへ渡したい場合、{…props}と書くことでまとめて転送できます8。ただし、多用しすぎるとコードの追いかけが難しくなるため、注意しましょう8
  2. 特別な「children」プロップ: コンポーネントのタグで囲んだ中身は、自動的にchildrenという特別な名前のPropとして子コンポーネントに渡されます8。これを使うと、デザインの「枠組み(カード型など)」を共通化して中身を自由に差し替えるといった、柔軟なレイアウト構築が可能になります13
    JavaScript
    function Card({ children }) {
      return <div className=”card-container”>{children}</div>;
    }
  3. イベントハンドラ(関数)の受け渡し: データは上から下にしか流せませんが、「ボタンが押された」などのイベントを子から親に伝えたいことがあります15。その場合は、親から子へ「関数」をPropsとして渡しておき、子の内部でその関数を実行します9

3. State(ステート)とは?「コンポーネントが自律的に管理する動的な記憶」

Stateは、コンポーネントの内部で保持されるデータであり、時間やユーザーの操作(クリックや文字入力など)によって変化するデータを指します1

なぜ普通の変数ではなくStateが必要なのか?

JavaScriptの通常の変数を書き換えても、Reactは「画面を更新しなさい」という命令を検知できません17。Stateとしてデータを管理することで、Reactはその値の変化を即座にキャッチし、自動的に関係するコンポーネントを再レンダリング(再描画)してくれます1

useStateフックを使った具体的なコード例

モダンなReact(関数コンポーネント)では、useStateという「フック(Hook)」を使ってStateを宣言します17

JavaScript

import React, { useState } from ‘react’;

function Counter() {
  // countというState変数と、それを更新するためのsetCount関数を用意します。初期値は0です。
  const [count, setCount] = useState(0);

  function handleClick() {
    // ボタンがクリックされたら、現在のカウントに1を足してStateを更新します
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      クリックされた回数: {count} 回
    </button>
  );
}

ボタンをクリックしてsetCountが実行されると、Reactは新しいcountの値を使って、このコンポーネントをもう一度実行(再レンダリング)し、画面の数字を書き換えます19

Stateを使う際の注意点:非同期とバッチ処理

Stateの動作には、いくつか特有のルールがあります。

  • 更新は「非同期」で行われます: setCountを呼び出した直後に、次の行でconsole.log(count)を実行しても、表示される値はまだ古いままです1。Stateの変更は、次のレンダリング時に反映されるようにスケジュールされるためです19
  • まとめて処理されます(バッチ処理): Reactはパフォーマンスを守るため、1つのイベントの中で複数回Stateが変更されても、可能な限りそれらをまとめて1回の再レンダリングで済ませようとします7
  • 前の値に基づいて更新する場合: 直前のStateの値を確実に使いたい場合は、setCount(count + 1)ではなく、setCount(prev => prev + 1)のように「更新用の関数」を渡す記述方法が推奨されます19

オブジェクトや配列のStateは「不変性(イミュータビリティ)」を守る

Stateにオブジェクトや配列を使う場合、既存のデータを直接書き換えてはいけません18。Reactは「データの参照先(メモリ上の住所)」が変わったかどうかで値の変化を判断するためです18

以下のように、常にスプレッド構文などを使って「新しいオブジェクトや配列のコピー」を作成して更新してください23

JavaScript

const [position, setPosition] = useState({ x: 0, y: 0 });

// ❌ 間違った方法(直接書き換えは検知されません)
// position.x = 100;
// setPosition(position);

// ⭕ 正しい方法(新しいオブジェクトを作って渡します)
setPosition(prev => ({
…prev,
  x: 100
}));

配列の場合も、pushやpopなどの元の配列を壊すメソッドは避け、filterやmap、スプレッド構文([…prev, ‘新しい要素’])のような非破壊的なメソッドを使いましょう17

4. PropsとStateの比較:使い分けの判断基準

PropsとStateは、どちらもコンポーネントの表示内容を変化させるものですが、明確な違いがあります。初心者の方は、以下の比較表を参考に使い分けてみてください。

一目でわかるPropsとStateの比較表

特徴・性質Props (プロパティ)State (ステート)
データの発生源親コンポーネントから渡される1コンポーネント自身が内部で作成する1
書き換えの可否受け取ったコンポーネントでは不変 (変更不可)2コンポーネント自身で自由に変更できる2
比喩表現関数の「引数」、外部からの「設定」1コンポーネント独自の「ローカル変数」「記憶」1
更新された時の動きPropsが変わると、その子コンポーネントが再描画される2Stateが変わると、自身と配下の子が再描画される1
主な用途表示する静的なデータや設定値、コールバック関数1フォームの入力値、開閉状態、APIから取得したデータ17

「ステートレス」と「ステートフル」のベストプラクティス

Reactのアプリケーションをきれいに保つためのコツは、「できるだけStateを持つコンポーネント(ステートフル)を減らし、Propsを受け取って表示するだけのコンポーネント(ステートレス)を増やす」ことです5

複雑なデータ処理や状態の管理は、ツリーの上部にある数少ない「ステートフルコンポーネント」に任せ、下部にある多くのコンポーネントは単にPropsを受け取ってきれいに表示することだけに集中させます。こうすることで、データの流れがシンプルになり、テストや修正が非常に楽になります5

5. コンポーネント間でデータを同期する「ステートの引き上げ」

「2つの異なるコンポーネントで、常に同じデータを同期させて表示したい」という場面がよくあります15。例えば、2つの入力フォームが常に同じ文字を表示する場合などです。

このとき、それぞれのコンポーネントで個別にStateを持たせてしまうと、お互いのデータを同期させることが難しくなります15。このような場合に使うのが、「ステートの引き上げ(Lifting State Up)」というパターンです24

ステートを引き上げる手順

  1. 子コンポーネントから独立したStateを削除する: 個々の子コンポーネントで記述していたuseStateを削除し、代わりにそのデータをPropsとして親から受け取るように書き換えます24
  2. 共通の親コンポーネントにStateを移動する: 同期させたい2つの子コンポーネントを包んでいる、共通の親(またはさらに上の先祖)コンポーネントを探し、そこにuseStateを宣言します15
  3. データと更新用関数を下に流す: 親コンポーネントから子コンポーネントへ、Stateの値と、そのStateを更新するための関数(イベントハンドラ)をそれぞれPropsとして受け渡します15

具体的なコード例:複数のパネルを同期させるアコーディオン

複数のパネルがあり、「1つのパネルが開いたら、もう片方のパネルは自動的に閉じる」というアコーディオンUIのコード例です。個々のパネルが「自分が開いているか」を管理するのではなく、親が「現在開いているパネルの番号」を管理します24

JavaScript

// 親コンポーネント:アコーディオン全体
function Accordion() {
  // 現在どのインデックス(0番目か1番目か)が開いているかをStateで管理します
  const [activeIndex, setActiveIndex] = useState(0);

  return (
    <>
      <Panel
        title=”セクション 1″
        isActive={activeIndex === 0}
        onShow={() => setActiveIndex(0)} // 更新用関数をPropsとして渡します
      >
        セクション1の詳しいコンテンツです。
      </Panel>
      <Panel
        title=”セクション 2″
        isActive={activeIndex === 1}
        onShow={() => setActiveIndex(1)}
      >
        セクション2の詳しいコンテンツです。
      </Panel>
    </>
  );
}

// 子コンポーネント:個々のパネル(自分の開閉状態を自分では決められない「制御された」状態)
function Panel({ title, children, isActive, onShow }) {
  return (
    <section className=”panel”>
      <h3>{title}</h3>
      {isActive? (
        <p>{children}</p>
      ) : (
        <button onClick={onShow}>表示する</button>
      )}
    </section>
  );
}

このように、データの「信頼できる唯一の情報源(Single Source of Truth)」を親に集約することで、表示の不整合が起きない頑丈なUIが完成します4

6. バケツリレー(Props Drilling)を防ぐための対策

コンポーネントの階層が5階層、10階層と深くなっていくと、一番上の親から一番下の子にデータを渡すために、途中のコンポーネントたちが自分では使わないPropsをただリレーのようにスルーして渡していくだけの状態が発生します27

これを「Props Drilling(プロップス・ドリリング、通称:バケツリレー)」と呼び、コードを複雑にしてしまう問題として知られています27

これに対処するためには、以下の方法が効果的です。

  • コンポーネント・コンポジション(構成): 不要な中継コンポーネントを排除し、childrenなどをうまく利用して、データを必要とするコンポーネント自体を親の段階ではめ込んでしまう手法です13
  • Context(コンテキスト)API: Reactに標準搭載されている機能で、ツリーの上の親から、中継コンポーネントをすべてスキップして、直接一番下の子コンポーネントへデータを届ける「ワープトンネル」のような仕組みを作ることができます12。ユーザーのカラーテーマやログイン中のアカウント情報など、アプリ全体で広く使うグローバルなデータ管理に最適です。

7. まとめ:データ設計をシンプルに保つことがReact上達のコツ

React開発の本質は、コンポーネントの分割設計と、データの流れ(PropsとState)をきれいに交通整理することにあります4

以下のチェックリストを常に頭の片隅に置いて、コードの設計を考えてみてください。

  1. そのデータは時間とともに変化しますか? 変化しないなら、それは単なる静的な変数や定数であり、Stateにする必要はありません4
  2. そのデータは親からPropsで受け取れますか? 受け取れるなら、自身でStateとして二重に持つ必要はありません4
  3. 他のStateやPropsから、単純な計算で導き出せますか? 例えば「商品の元の値段」と「割引率」のStateがあれば、「割引後の値段」をわざわざ3つ目のStateとして保存する必要はありません4。レンダリングの最中にその場で引き算をして表示するのが、最もバグの出ない正しい方法です。

Propsによる「設定の外部化」と、Stateによる「状態の自己管理」を上手に使い分け、クリーンでメンテナンスのしやすいReactコードを書いていきましょう!

引用文献

  1. Component State – React, 5月 7, 2026にアクセス、 https://legacy.reactjs.org/docs/faq-state.html
  2. Understanding React: Props vs. State | Medium, 5月 7, 2026にアクセス、 https://medium.com/@dudhatrayashraj/props-and-state-in-react-ba9819cbba74
  3. Components and Props – React, 5月 7, 2026にアクセス、 https://legacy.reactjs.org/docs/components-and-props.html
  4. Thinking in React – React, 5月 7, 2026にアクセス、 https://react.dev/learn/thinking-in-react
  5. What is the difference between state and props in React? – Stack Overflow, 5月 7, 2026にアクセス、 https://stackoverflow.com/questions/27991366/what-is-the-difference-between-state-and-props-in-react
  6. React Props vs State: What’s the Difference? – DEV Community, 5月 7, 2026にアクセス、 https://dev.to/highflyer910/react-props-vs-state-whats-the-difference-4e3i
  7. What is The Difference Between State and Props in React? – Flatlogic Blog, 5月 7, 2026にアクセス、 https://flatlogic.com/blog/what-is-the-difference-between-state-and-props-in-react/
  8. Passing Props to a Component – React, 5月 7, 2026にアクセス、 https://react.dev/learn/passing-props-to-a-component
  9. Props and State in React: Differences and Usage Scenarios | by Tuğçe Çifci | Medium, 5月 7, 2026にアクセス、 https://medium.com/@tucecifcii/props-and-state-in-react-differences-and-usage-scenarios-fb292f74998e
  10. React Propsとは?たったの「3分」で理解|親子コンポーネントでのデータ渡し方をコード付きで解説 – LifeCode, 5月 7, 2026にアクセス、 https://lifecodeworks.com/tech/react-props-beginner-guide/
  11. Passing object as props to jsx – reactjs – Stack Overflow, 5月 7, 2026にアクセス、 https://stackoverflow.com/questions/49081549/passing-object-as-props-to-jsx
  12. Passing props to child components in React function components – CoreUI, 5月 7, 2026にアクセス、 https://coreui.io/blog/passing-props-to-child-components-in-react-function-components/
  13. 【React】Props のバケツリレー解消法について – Zenn, 5月 7, 2026にアクセス、 https://zenn.dev/rh820/articles/bd8e97fd315cfa
  14. propsバケツリレー問題をコンポジションで解消し、コンポーネントの単一責務を取り戻す – Zenn, 5月 7, 2026にアクセス、 https://zenn.dev/hmochizuki/articles/a7edd55ed1e459
  15. Lifting State Up in ReactJS – GeeksforGeeks, 5月 7, 2026にアクセス、 https://www.geeksforgeeks.org/reactjs/lifting-state-up-in-reactjs/
  16. React入門 – コンポーネント、JSX、Props、Stateの基本 – Zenn, 5月 7, 2026にアクセス、 https://zenn.dev/three_dots_inc/articles/0a479f9dc61bf2
  17. React Hooks: useState (With Practical Examples) | by Tito Adeoye – Medium, 5月 7, 2026にアクセス、 https://medium.com/@titoadeoye/react-hooks-usestate-with-practical-examples-64abd6df6471
  18. State(useState)|React入門 2026 – モダンなReact開発を基礎から学ぶ – Zenn, 5月 7, 2026にアクセス、 https://zenn.dev/rasshii/books/learning-react-2026/viewer/07-state
  19. useState – React, 5月 7, 2026にアクセス、 https://react.dev/reference/react/useState
  20. React の state とは何かを改めて整理した – Qiita, 5月 7, 2026にアクセス、 https://qiita.com/ryo_sh/items/ef1af33a71b1e4ead816
  21. Using the State Hook – React, 5月 7, 2026にアクセス、 https://legacy.reactjs.org/docs/hooks-state.html
  22. Reactのstateとは?更新は即時反映されない。オブジェクト型、プリミティブ型などの注意点 – Qiita, 5月 7, 2026にアクセス、 https://qiita.com/kenogi/items/be5a062524cc7578acd3
  23. useState in React: A complete guide – LogRocket Blog, 5月 7, 2026にアクセス、 https://blog.logrocket.com/guide-usestate-react/
  24. Sharing State Between Components – React, 5月 7, 2026にアクセス、 https://react.dev/learn/sharing-state-between-components
  25. state のリフトアップ – React, 5月 7, 2026にアクセス、 https://ja.legacy.reactjs.org/docs/lifting-state-up.html
  26. Lesson 4 – Lifting State Up – React Pattern Overview | ReactJS-The Beginner Master Class, 5月 7, 2026にアクセス、 https://reactjs.koida.tech/react-state-and-styling/lesson-4-lifting-state-up-react-pattern-overview
  27. How props are passed to components in React – LogRocket Blog, 5月 7, 2026にアクセス、 https://blog.logrocket.com/how-props-passed-components-react/
  28. Reactのprops drilling(バケツリレー)とhooksに我々はどう立ち向かっていけばよいのか, 5月 7, 2026にアクセス、 https://blog.asobou.co.jp/web/props-drilling
  29. ReactでContext APIを使う前にやるべきprops drilling問題の解消法 – i3DESIGN Tech Blog, 5月 7, 2026にアクセス、 https://tech.i3design.jp/react-props-drilling-composition/
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次