Closed12

「Learn Next.js / React Foundations」

ゆーとゆーと

React Foundations

What is React?

Reactは、インタラクティブなユーザーインターフェースを構築するためのJavaScriptライブラリである。
ユーザー・インターフェースとは、ユーザーが画面上で見たり操作したりする要素を意味します。


What is Next.js?

Next.jsは、Webアプリケーションを作成するためのビルディングブロックを提供するReactフレームワークです。
フレームワークとは、Next.jsがReactに必要なツールや設定を処理し、アプリケーションに追加の構造、機能、最適化を提供することを意味します。

Reactを使ってUIを構築し、Next.jsの機能を段階的に採用して、ルーティング、データ取得、統合などの一般的なアプリケーション要件を解決することができます。


Pre-requisite knowledge

このチュートリアルでは、HTML、CSS、JavaScriptの知識があり、Reactの知識がないことを前提としています。すでにReactに慣れている場合は、「Next.jsを始める」セクションまたは「最初のNext.jsアプリを作成する」セクションに進んでください。

ゆーとゆーと

Chapter 1 / Rendering User Interfaces

HTMLのレンダリングの図解とDOMの図解

ゆーとゆーと

Chapter 2 / Updating UI with Javascript

<div id="app"></div>

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

純粋なJSでHTMLのDOM操作をするのは強力だが助長。
しかも規模が大きくなるとかなり難しくなる。
この命令型プログラミング(ここではDOMメソッドの記載)を、宣言型プログラミングにできたら便利。

命令型でDOM操作して、結果、h1タグが生成される。
ではなく、宣言型で「h1タグを作って」と宣言するだけでh1タグを生成してくれたら便利。

例えるなら、命令型プログラミングは、シェフにピザの作り方をステップ・バイ・ステップで指示するようなものだ。宣言的プログラミングは、ピザを作る手順を気にせずにピザを注文するようなもの。

開発者がユーザーインターフェースを構築するのに役立つ人気のある宣言型ライブラリーにReactがある。

React: A declarative UI library

開発者としては、ユーザーインターフェイスに何を起こしたいかをReactに伝えれば、Reactがあなたの代わりにDOMを更新する手順を考えてくれる。

次のセクションでは、Reactをどのように使い始められるかを探っていく。


命令型で冗長にもなりやすいJSを、宣言型のRectにすれば簡潔にできる。

ゆーとゆーと

Chapter 3 / Getting Started with React

プロジェクトでReactを使用するには、unpkg.comという外部のウェブサイトから2つのReactスクリプトを読み込むことができます。

  • reactは、Reactのコア・ライブラリ。
  • react-domは、ReactをDOMで使用できるようにするDOM固有のメソッドを提供する。

素のJavaScriptで直接DOMを操作する代わりに、react-domのReactDOM.render()メソッドを使って、Reactに#app要素内の<h1>タイトルをレンダリングするように指示することができます。

<html>
  <body>
    <div id="app"></div>
 
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
 
    <script type="text/javascript">
      const app = document.getElementById('app');
      ReactDOM.render(<h1>Develop. Preview. Ship. 🚀</h1>, app);   <!-- error -->
    </script>
  </body>
</html>

しかし、このコードをブラウザで実行しようとすると、シンタックス・エラーが発生する。
これは<h1>...</h1>が有効なJavascriptではないからです。このコードはJSXです。


What is JSX?

JSXはJavaScriptの構文拡張で、使い慣れたHTMLのような構文でUIを記述できる。
JSXの良いところは、3つのJSXルールに従うことを除けば、HTMLとJavaScript以外の新しいシンボルや構文を学ぶ必要がないことです。

ブラウザはJSXをそのまま理解するわけではないので、JSXコードを通常のJavaScriptに変換するにはBabelのようなJavaScriptコンパイラが必要です。

<html>
  <body>
    <div id="app"></div>
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <!-- Babel Script -->
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/jsx">
      const app = document.getElementById('app');
+      ReactDOM.render(<h1>Develop. Preview. Ship. 🚀</h1>, app);
-      // const header = document.createElement('h1');
-      // const headerContent = document.createTextNode('Develop. Preview. Ship. 🚀');
-      // header.appendChild(headerContent);
-      // app.appendChild(header);
    </script>
  </body>
</html>

Reactを使うことで、繰り返しのコードを大幅に削減できることがおわかりいただけるだろう。

Reactは、あなたの代わりにタスク(この場合はUIの更新)を実行する、再利用可能なコードの断片を含むライブラリなのだ。


javascriptライブラリであるreactを使用する際に、jsx形式を使用するとhtml形式と同じような記載でreact(js)のコードが書ける。これによって直感的に見やすく、また動的に値も渡すことができる。

ゆーとゆーと

Chapter 4 / Essential Javascript for React

JavaScriptとReactを同時に学ぶことは可能だが、JavaScriptに精通していれば、Reactを学ぶプロセスを容易にすることができる。

次のセクションでは、JavaScriptの観点からReactの中核となる概念を紹介します。
ここでは、JavaScriptのトピックについて説明します:

  • Functions and Arrow Functions
  • Objects
  • Arrays and array methods
  • Destructuring
  • Template literals
  • Ternary Operators
  • ES Modules and Import / Export Syntax

このコースではJavaScriptについて深く掘り下げませんが、JavaScriptの最新バージョンに常に触れておくことは良い練習になります。
しかし、まだJavaScriptに習熟していないと感じても、Reactを使ったビルドを始めるのに支障はありません!


React core concepts

Reactアプリケーションを作り始めるには、Reactの3つのコア・コンセプトに精通している必要がある。それは以下の3つです:

  • Components
  • Props
  • State
ゆーとゆーと

Chapter 5 / Building UI with Components

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

コンポーネントによって、自己完結的で再利用可能なコードの断片を構築することができる。
コンポーネントをレゴブロックと考えれば、個々のレゴブロックを組み合わせて、より大きな構造を作ることができる。
UIの一部を更新する必要がある場合は、特定のコンポーネントやレンガを更新することができます。

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

Reactコンポーネントのいいところは、単なるJavaScriptであることだ。
JavaScriptの視点から、Reactコンポーネントの書き方を見てみよう:


Creating components

Reactでは、コンポーネントは関数である。
scriptタグの中に、headerという関数を書きます:

コンポーネントとは、UI要素を返す関数のことです。
関数のreturn文の中に、JSXを書くことができます:

このコンポーネントをDOMにレンダリングするには、ReactDOM.render()メソッドの第1引数に渡します:

<script type="text/jsx">
 
  const app = document.getElementById("app")
 
  function header() {
     return (<h1>Develop. Preview. Ship. 🚀</h1>)
   }
  
   ReactDOM.render(header, app)
</script>

しかし、ちょっと待ってほしい。上のコードをブラウザで実行しようとすると、エラーが出る。これを動作させるには、やらなければならないことが2つある:

まず、Reactコンポーネントは大文字にして、プレーンなHTMLやJavaScriptと区別すること。
次に、Reactコンポーネントは、通常のHTMLタグと同じように、角括弧<>で囲んで使う。

function Header() {
  return <h1>Develop. Preview. Ship. 🚀</h1>;
}
 
ReactDOM.render(<Header />, app);

Nesting components

アプリケーションには通常、1つのコンポーネントよりも多くのコンテンツが含まれる。
通常のHTML要素と同じように、Reactコンポーネント同士を入れ子にすることができる。

この例では、HomePageという新しいコンポーネントを作成します:
そして、新しい<HomePage>コンポーネントの中に<Header>コンポーネントをネストします:

function Header() {
  return <h1>Develop. Preview. Ship. 🚀</h1>;
}
 
function HomePage() {
  return (
    <div>
      {/* Nesting the Header component */}
      <Header />
    </div>
  );
}
 
ReactDOM.render(<Header />, app);
<!-- or ReactDOM.render(<HomePage />, app);  -->

Component trees


このようにReactコンポーネントをネストし続けることで、コンポーネント・ツリーを形成することができる。

例えば、トップレベルのHomePageコンポーネントは、Header、Article、Footerコンポーネントを持つことができます。そして、それらの各コンポーネントは順番にそれ自身の子コンポーネントなどを持つことができます。例えば、ヘッダーコンポーネントはロゴ、タイトル、ナビゲーションコンポーネントを含むことができます。

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

プロジェクトでは、<HomePage>がトップレベルのコンポーネントになっているので、ReactDOM.render()メソッドに渡すことができます:


ReactのコンポーネントはUIを返すJavaScriptの関数。

ゆーとゆーと

Chapter 6 / Displaying Data with Props

これまでのところ、<Header />コンポーネントを再利用すると、どちらも同じ内容が表示されます。

しかし、異なるテキストを渡したい場合や、外部ソースからデータをフェッチしているため事前に情報がわからない場合はどうすればいいのだろうか?

通常のHTML要素には属性があり、それを使って要素の動作を変える情報を渡すことができます。
例えば、<img>要素のsrc属性を変更すると、表示される画像が変わります。
<a>タグのhref属性を変更すると、リンク先が変わります。

同じように、Reactコンポーネントにも、情報の断片をプロパティとして渡すことができます。
これらをpropsと呼びます。

JavaScriptの関数と同様に、コンポーネントの動作や、画面にレンダリングされたときに表示される内容を変更するカスタム引数(またはprops)を受け付けるコンポーネントを設計できます。
そして、これらのpropsを親コンポーネントから子コンポーネントに渡すことができます。

注:Reactでは、データはコンポーネントツリーを流れていきます。これを一方向データフローと呼ぶ。
次のセクションで説明するステートは、propsとして親コンポーネントから子コンポーネントに渡すことができます。


Using props

HomePageコンポーネントでは、HTML属性を渡すのと同じように、カスタムタイトルプロパティをHeaderコンポーネントに渡すことができます:

そして、子コンポーネントであるHeaderは、その最初の関数パラメータとしてこれらのpropsを受け取ることができます:

console.log()のプロパティを見ると、titleプロパティを持つオブジェクトであることがわかる。

propsはオブジェクトなので、オブジェクトのdestructuringを使用して、関数のパラメータ内でpropsの値を明示的に指定することができます:
表示する際はJavaScript変数であることをReactに示す方法が必要です。

Using variables in JSX

定義した変数を使用するには、中括弧{}を使用します。
これは、JSXマークアップの中に通常のJavaScriptを直接書くことができる特別なJSX構文です。

コンポーネントは、アプリケーションのさまざまな部分で再利用できる一般的なタイトルのプロップを受け入れるようになりました。
以下の例だと、必要なのはtitleを変更することだけです:

    function Header(props) {
        console.log(props);
        console.log(props.title);
        return <h1>{props.title}</h1>;
      }
   <!-- destructuringでやるなら以下 -->
    function Header({title}) {
        console.log(title);
        return <h1>{title}</h1>;
      }
                  
      function HomePage() {
        return (
          <div>
            <Header title="React 💙" />
        </div>
        );
      }


Iterating through lists

リストとして表示する必要のあるデータがあることはよくあることです。
配列メソッドを使用してデータを操作し、同じスタイルで異なる情報を保持するUI要素を生成することができます。

function HomePage() {
  const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
 
  return (
    <div>
      <Header title="Develop. Preview. Ship. 🚀" />
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>
    </div>
  );
}

propsという名のオブジェクトを関数の引数として渡して値を取り扱う。

ゆーとゆーと

Chapter 7 / Adding Interactivity with State

Reactが、stateとイベント・ハンドラを使ってどのようにインタラクティビティを追加してくれるのかを探ってみよう。

例として、HomePageコンポーネントの中に「いいね!」ボタンを作ってみましょう。

function HomePage() {
  // 	...
  function handleClick() {
    console.log('increment like count');
  }
 
  return (
    <div>
      {/* ... */}
      <button onClick={handleClick}>Like</button>
    </div>
  );
}


State and hooks

Reactにはhooksと呼ばれる関数群がある。
hooksを使えば、stateのような追加ロジックをコンポーネントに追加できる。
stateとは、時間の経過とともに変化するUIの情報のことで、通常はユーザーとのインタラクションがトリガーになります。

ユーザーが「いいね!」ボタンをクリックした回数を保存し、インクリメントするためにステートを使用することができます。
実際、ステートを管理するためのReactフックの名前はこうなっている: useState()

useState() は配列を返すので、配列のdestructuringを使って、 コンポーネントの内部で配列の値にアクセスして使用することができます:

配列の最初の項目はstate値で、名前は何でもよい。わかりやすい名前をつけることをお勧めする:

配列の2番目の項目は、値を更新する関数です。update関数の名前は何でもかまいませんが、setの前に更新するstate変数の名前をつけるのが一般的です:

好きな状態の初期値「ゼロ」を追加することもできる。

ボタンをクリックすると、handleClick関数が呼び出され、setLikes状態更新関数が、現在の「いいね!」数+1を引数として呼び出されます。

      function HomePage() {
        const [likes, setLikes] = React.useState(0);

        function handleClick() {
          setLikes(likes + 1);
        }
      
        return (
          <div>
            // ...
            </ul>
            <button onClick={handleClick}>Like({likes})</button>
          </div>
        );
      }
                        
      ReactDOM.render(<HomePage />, app);

注意:
最初の関数パラメータとしてコンポーネントに渡されるpropsとは異なり、状態はコンポーネント内で開始され、保存されます。
子コンポーネントにpropsとしてstate情報を渡すことはできますが、stateを更新するロジックは、ステートが最初に作成されたコンポーネント内に保持する必要があります。

≒ 上記例で言うと、likesは値参照として他のコンポーネントに渡すのはOK。
setLikesを他のコンポーネントに渡して、他のコンポーネント内でstateを変更するのは非推奨。


Managing State

Reactアプリケーションでステートとデータフローを管理する方法については、まだまだ学ぶことがあります。さらに詳しく学ぶには、ReactドキュメントのAdding InteractivityManaging Stateのセクションを参照することをお勧めします。


Stateはコンポーネント内で完結させる。やり取りする際は純粋な値のみ。

ゆーとゆーと

Chapter 8 / From React to Next.js

Reactに不可欠な3つの概念、components, props, stateを紹介しました。
これらの基礎をしっかり身につけることで、Reactアプリケーションを作り始めるのに役立ちます。
自信がついたら、他のReactトピックもチェックしてみてください:


React resources

何年もの間、開発者がReactを学ぶのに役立つ多くのコース、ビデオ、記事が作られてきた。
あなたの学習スタイルに合ったリソースを推薦するのは難しいが、貴重な参考資料の1つはReact Documentationで、Reactの各トピックを練習するのに役立つインタラクティブなサンドボックス(≒実際にコードを書いて試し、結果をリアルタイムで確認できるオンラインコーディング環境)が含まれている。

Reactの学習に関しては、構築することが最良の学習方法だ。
<script>とこれまでに学んだことを使って、既存のウェブサイトに小さなコンポーネントを追加することで、徐々にReactを採用することができる。
しかし、多くの開発者は、Reactが可能にするユーザーと開発者の体験に十分な価値を見出し、すぐに飛び込んでフロントエンドのプロジェクト全体をReactで書いています。

From React to Next.js

ReactはUIを構築することに優れていますが、そのUIを完全に機能するスケーラブルなアプリケーションに独自に構築するには、ある程度の作業が必要です。
朗報は、Next.jsがセットアップと設定の多くを処理し、Reactアプリケーションの構築を支援する追加機能を備えていることです。

次に、サンプルをReactからNext.jsに移行し、Next.jsがどのように動作するかを説明し、より高度なNext.jsの機能を学ぶのに役立つWeb開発の概念を紹介します。

ゆーとゆーと

Chapter 9 / Installing Next.js

Next.jsをプロジェクトに追加する方法が記載。

今までのサンプルのフォルダ
- page.html
Next.js追加後ののフォルダ構成
├ node_modules
├ pages
│ └─ index.js
├ package-lock.json
├ package.json

Next.js追加後は元のhtmlファイルはJSXのみとなるので、.htmlから.jsxか.jsに変更できる。
Next.jsアプリに完全に移行するには、あと3つのことが必要です:

  1. index.jsファイルをpagesという新しいフォルダに移動する
  2. メインのReactコンポーネントにdefault exportを追加して、Next.jsがどのコンポーネントをこのページのメインコンポーネントとしてレンダリングするかを区別できるようにします。
  3. 開発中にNext.js開発サーバーを実行するスクリプトをpackage.jsonファイルに追加します。


Running the development server

すべてがうまくいくことを確認するには、ターミナルでnpm run devを実行し、ブラウザでlocalhost:3000に移動してアプリを表示することができる。それからコードを少し変更して保存する。

ファイルを保存すると、ブラウザが自動的に更新され、変更が反映されていることに気づくはずだ。

この機能は高速リフレッシュと呼ばれています。Next.jsにあらかじめ設定されています。

.htmlから.jsへの変更コード
.html
<html>
  <body>
    <div id="app"></div>
 
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
 
    <script type="text/jsx">
      const app = document.getElementById("app")
 
      function Header({ title }) {
        return <h1>{title ? title : "Default title"}</h1>
      }
 
      function HomePage() {
        const names = ["Ada Lovelace", "Grace Hopper", "Margaret Hamilton"]
        const [likes, setLikes] = React.useState(0)
 
        function handleClick() {
          setLikes(likes + 1)
        }
 
        return (
          <div>
            <Header title="Develop. Preview. Ship. 🚀" />
            <ul>
              {names.map((name) => (
                <li key={name}>{name}</li>
              ))}
            </ul>
 
            <button onClick={handleClick}>Like ({likes})</button>
          </div>
        )
      }
 
      ReactDOM.render(<HomePage />, app)
    </script>
  </body>
</html>
.js
import { useState } from 'react';
 
function Header({ title }) {
  return <h1>{title ? title : 'Default title'}</h1>;
}
 
export default function HomePage() {
  const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
  const [likes, setLikes] = useState(0);
 
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return (
    <div>
      <Header title="Develop. Preview. Ship. 🚀" />
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>
 
      <button onClick={handleClick}>Like ({likes})</button>
    </div>
  );
}


Reactは、モダンなインタラクティブUIを構築するために不可欠なプリミティブを提供するライブラリだ。
しかし、作成したUIをアプリケーションにまとめるには、まだいくつかの作業が必要だ。

マイグレーションを見ると、Next.jsを使う利点がすでに感じられるかもしれません。
babelスクリプトが削除され、複雑なツール設定を考える必要がなくなりました。
また、Next.jsで期待できる数多くの開発者体験機能のひとつであるFast Refreshの動作もご覧いただけたことでしょう。

ゆーとゆーと

Next Steps

今までをまとめると、ReactとNext.jsの基礎知識を学び、シンプルなReactアプリケーションからNext.jsアプリケーションに移行しました。

次のステップです:

  1. 最初のアプリを作成してNext.jsの使い方を学ぶ - このコースでは、Next.jsの主な機能を紹介し、より複雑なプロジェクトを作成して練習します。

次のレッスンでは、Next.jsがどのように動作するのかを、関連するWeb開発のコンセプトを紹介しながら探ります。
これらの概念に精通することで、基礎が広がり、より高度なNext.jsの機能を学びやすくなります。

このスクラップは2023/11/15にクローズされました