🧩

ゼロから学ぶ React, Next.js③【React Foundations】Chapter4,5

2024/05/24に公開

公式チュートリアルはこちら
https://nextjs.org/learn/react-foundations/getting-started-with-react
https://nextjs.org/learn/react-foundations/building-ui-with-components

React を始める

新しく作成したプロジェクトで React を使用するには、unpkg.com という外部の Web サイトから 2 つの React スクリプトを読み込みます。

メモ:unpkg.comとは

npmで公開されているパッケージをscriptタグ等で指定することで、ローカルにライブラリを落とすことなくライブラリを使用することができるサービスです。

  • react は React のコアライブラリです。
  • react-dom は、React を DOM で使用できるようにする DOM 固有のメソッドを提供します。
index.html
 <html>
  <body>
    <div id="app"></div>
+   <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
+   <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script type="text/javascript">
     const app = document.getElementById('app');
     const header = document.createElement('h1');
     const text = 'Develop. Preview. Ship.';
     const headerContent = document.createTextNode(text);
     header.appendChild(headerContent);
     app.appendChild(header);
    </script>
  </body>
 </html>

プレーンな JavaScript で直接 DOM を操作する代わりに、以前に追加した DOM メソッドを削除し、ReactDOM.createRoot() メソッドを追加して特定の DOM 要素をターゲットにし、React コンポーネントを表示するためのルートを作成します。次に、root.render() メソッドを追加して、React コードを DOM にレンダリングします。

これにより、React は #app 要素内に <h1> タイトルをレンダリングするように指示されます。

index.html
 <html>
  <body>
    <div id="app"></div>
   <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
   <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script type="text/javascript">
     const app = document.getElementById('app');
-     const header = document.createElement('h1');
-     const text = 'Develop. Preview. Ship.';
-     const headerContent = document.createTextNode(text);
-     header.appendChild(headerContent);
-     app.appendChild(header);
+     const root = ReactDOM.createRoot(app);
+     root.render(<h1>Develop. Preview. Ship.</h1>);
    </script>
  </body>
 </html>

このコードをブラウザで実行しようとすると、構文エラーが発生します。
devtools のコンソールには次のエラーメッセージが表示されます。

これは、<h1>...</h1> が有効な Javascript ではないためです。このコードは JSX です。


JSX とは?

JSX は JavaScript の構文拡張であり、馴染みのある HTML のような構文で UI を記述できます。JSX の良い点は、3つのJSXルールに従うだけで、HTML と JavaScript 以外の新しい記号や構文を学ぶ必要がないことです。

メモ:3つのJSXルールとは

1. 単一のルート要素を返す

コンポーネントから複数の要素を返すには、それらを1つの要素で囲む必要があります。
例えば、<div> を使うことができます。

jsx
<div>
  <h1>title</h1>
  <p>text</p>
</div>

マークアップに余分な <div> を追加したくない場合は、代わりに <></> を書くことができます。

jsx
<>
  <h1>title</h1>
  <p>text</p>
</>

この空のタグは Fragment と呼ばれます。Fragments を使用すると、ブラウザの HTML ツリーに痕跡を残さずにグループ化できます。

2. すべてのタグを閉じる

JSX では、タグを明示的に閉じる必要があります。<img> のような自己終了タグは <img /> になり、<li>oranges のようなラップタグは <li>oranges</li> と書く必要があります。

jsx
<>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
   />
  <ul>
    <li>Invent new traffic lights</li>
    <li>Rehearse a movie scene</li>
    <li>Improve the spectrum technology</li>
  </ul>
</>

3.ほとんどのものをcamelCaseにする

JSX は JavaScript に変換され、JSX で書かれた属性は JavaScript オブジェクトのキーになります。しかし、JavaScript には変数名に制限があります。例えば、変数名にダッシュを含めることはできませんし、class のような予約語にすることもできません。
そのため、React では多くの HTML および SVG 属性が camelCase で書かれています。例えば、stroke-width の代わりに strokeWidth を使用します。class は予約語なので、React では対応する DOM プロパティにちなんで className と書きます。

jsx
<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Hedy Lamarr" 
  className="photo"
/>

ただし、ブラウザは JSX をそのまま理解できないため、Babel などの JavaScript コンパイラを使用して、JSX コードを通常の JavaScript に変換する必要があります。


プロジェクトに Babel を追加する

プロジェクトに Babel を追加するには、次のスクリプトを index.html ファイルにコピーして貼り付けます。

index.html
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

さらに、スクリプトタイプを type=text/jsx に変更して、Babel にどのコードを変換するかを通知する必要があります。

index.html
 <html>
  <body>
    <div id="app"></div>
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <!-- Babel Script -->
+   <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
+    <script type="text/jsx">
     const domNode = document.getElementById('app');
     const root = ReactDOM.createRoot(domNode);
     root.render(<h1>Develop. Preview. Ship.</h1>);
    </script>
  </body>
 </html>

正しく動作していることを確認するには、ブラウザで HTML ファイルを開きます。

先ほど記述した宣言型の React コード:

index.html
<script type="text/jsx">
 const domNode = document.getElementById("app")
 const root = ReactDOM.createRoot(domNode);
 root.render(<h1>Develop. Preview. Ship.</h1>);
</script>

を、前のセクションで記述した命令型の JavaScript コード:

index.html
<script type="text/javascript">
 const app = document.getElementById('app');
 const header = document.createElement('h1');
 const text = 'Develop. Preview. Ship.';
 const headerContent = document.createTextNode(text);
 header.appendChild(headerContent);
 app.appendChild(header);
</script>

と比較すると、React を使用することで多くの繰り返しのコードを削減できることがわかり始めます。

そして、これこそが React がすることです。React は、あなたに代わってタスクを実行する再利用可能なコードのスニペットを含むライブラリです。この場合は、UI を更新することです。

追加のリソース

React が UI をどのように更新するかを正確に知る必要はありませんが、もっと詳しく知りたい場合は、以下のような追加リソースがあります。


React に不可欠な JavaScript

JavaScript と React を同時に学ぶことはできますが、JavaScript に精通していると React の学習プロセスが容易になります。

次のセクションでは、JavaScript の観点から React のいくつかの中核となる概念を紹介します。言及される JavaScript のトピックの概要は次のとおりです。

  • 関数とアロー関数
  • オブジェクト
  • 配列と配列メソッド
  • 分割代入
  • テンプレートリテラル
  • 三項演算子
  • ES モジュールとインポート/エクスポート構文

このコースでは JavaScript について詳しく説明しませんが、JavaScript の最新バージョンを常に把握しておくことをお勧めします。ただし、JavaScript にまだ精通していないからといって、React での構築を始めることを妨げてはいけません!

【Chapter5】 コンポーネントで UI を構築する

React のコア概念

React アプリケーションの構築を始めるためには、React の 3 つのコア概念に精通する必要があります。これらは以下の通りです。

  • コンポーネント
  • Props
  • State

次の章では、これらの概念について説明し、学習を続けるためのリソースを提供します。これらの概念に精通した後、Next.js のインストール方法と、Server コンポーネントや Client コンポーネントなどの新しい React 機能の使用方法をお見せします。

コンポーネント

ユーザーインターフェースは、コンポーネントと呼ばれるより小さな構成要素に分割できます。

コンポーネントを使用すると、自己完結型の再利用可能なコードスニペットを構築できます。コンポーネントを LEGO ブロックのように考えると、これらの個々のブロックを組み合わせてより大きな構造を形成できます。UI の一部を更新する必要がある場合は、特定のコンポーネントまたはブロックを更新するだけで済みます。

メモ:コードスニペットとは

よく使われる短いコードの断片に分かりやすい名前を付け、簡単な操作でソース・コードに挿入可能にしたものです。[1]

コンポーネントの例

このモジュール性により、アプリケーションの残りの部分に触れることなくコンポーネントを追加、更新、削除できるため、コードが大きくなっても保守性が向上します。

React コンポーネントの良い点は、単なる JavaScript であることです。JavaScript の観点から、React コンポーネントの書き方を見てみましょう。

コンポーネントの作成

React では、コンポーネントは関数です。script タグ内に、header という新しい関数を作成します。

index.html
 <script type="text/jsx">
   const app = document.getElementById("app")
 
+  function header() {
+  }
 
   const root = ReactDOM.createRoot(app);
   root.render(<h1>Develop. Preview. Ship.</h1>);
 </script>

コンポーネントは、UI 要素を返す関数です。関数の return ステートメント内で、JSX を記述できます。

index.html
 <script type="text/jsx">
   const app = document.getElementById("app")
 
   function header() {
+     return (<h1>Develop. Preview. Ship.</h1>)
    }
 
   const root = ReactDOM.createRoot(app);
   root.render(<h1>Develop. Preview. Ship.</h1>);
 </script>

このコンポーネントを DOM にレンダリングするには、root.render() メソッドの最初の引数として渡します。

index.html
 <script type="text/jsx">
   const app = document.getElementById("app")
 
   function header() {
      return (<h1>Develop. Preview. Ship.</h1>)
   }
 
  const root = ReactDOM.createRoot(app);
+  root.render(header);
 </script>

上記のコードをブラウザで実行しようとすると、エラーが発生します。これを動作させるには、2 つのことを行う必要があります。

まず、React コンポーネントは、プレーンな HTML や JavaScript と区別するために大文字で始める必要があります。

index.html
+function Header() {
  return <h1>Develop. Preview. Ship.</h1>;
}
 
const root = ReactDOM.createRoot(app);
// React コンポーネントを大文字で始める
+root.render(Header);

次に、React コンポーネントは、通常の HTML タグと同じように、山括弧 <> を使用します。

index.html
function Header() {
  return <h1>Develop. Preview. Ship.</h1>;
}
 
const root = ReactDOM.createRoot(app);
+root.render(<Header />);

再度ブラウザでコードを実行すると、変更内容が表示されます。

コンポーネントのネスト

アプリケーションには通常、単一のコンポーネント以上のコンテンツが含まれています。React コンポーネントを通常の HTML 要素のように互いにネストできます。

この例では、HomePage という新しいコンポーネントを作成します。

index.html
function Header() {
  return <h1>Develop. Preview. Ship.</h1>;
}
 
+ function HomePage() {
+   return <div></div>;
+ }
 
const root = ReactDOM.createRoot(app);
root.render(<Header />);

次に、新しい <HomePage> コンポーネント内に <Header> コンポーネントをネストします。

index.html
function Header() {
  return <h1>Develop. Preview. Ship.</h1>;
}
 
function HomePage() {
  return (
+    <div>
+      {/* Header コンポーネントのネスト */}
+      <Header />
+    </div>
  );
}
 
const root = ReactDOM.createRoot(app);
root.render(<Header />);

コンポーネントツリー

この方法で React コンポーネントをネストし続けると、コンポーネントツリーが形成されます。
React

コンポーネントがどのように互いにネストできるかを示すコンポーネントツリー

例えば、トップレベルの HomePage コンポーネントには、HeaderArticleFooter コンポーネントを含めることができます。そして、それらのコンポーネントはそれぞれ独自の子コンポーネントを持つことができます。例えば、Header コンポーネントには、LogoTitleNavigation コンポーネントを含めることができます。

このモジュール形式により、アプリ内の異なる場所でコンポーネントを再利用できます。

このプロジェクトでは、<HomePage> が現在トップレベルのコンポーネントであるため、これを root.render() メソッドに渡すことができます。

index.html
function Header() {
  return <h1>Develop. Preview. Ship.</h1>;
}
 
function HomePage() {
  return (
    <div>
      <Header />
    </div>
  );
}
 
const root = ReactDOM.createRoot(app);
+ root.render(<HomePage />);

追加のリソース


次の章

https://zenn.dev/gunjo/articles/ddc322aa54c282

脚注
  1. https://atmarkit.itmedia.co.jp/fdotnet/vb2005/vb2005_07/vb2005_07_01.html ↩︎

Discussion