はじめに
この記事を書こうと思った経緯
近年、フロントエンドで主流であるReactとNext.jsがどんな技術なのかを知りたく、結局のところどこまでの知識があればアプリケーションを作れるのかわからなかったのでまとめてみました。
この記事で書く内容について
私がReactとNext.jsでアプリケーションを作ったときに、どんな知識が最低限必要だったかをまとめてみました。
また、文字だと伝わりにくいかと思いなるべくコードを乗せるようにしてみた。
コードについてはcodesandboxという公式Reactのドキュメントも使っているサービスを使って作成しました。
注意点として
- 公式ページにあるすべての技術を網羅してはいない。
- 基本的には必要な知識のまとめであり、この記事を通して何らかのアプリを作ったりはしない
学習の流れ
-
第1回【React】:React入門 — コンポーネントとJSXの基本
- Reactとは何か、コンポーネントについて学ぶ
-
第2回【React】:フック入門 — useState と useEffect
- useState と useEffectというReactの関数を学ぶ
-
第3回【React】:コンポーネント間で値を共有する方法
- 複数のコンポーネントを作ったときの値の共有方法を学ぶ
-
第4回【Next.js】:Next.jsの基本
- Next.jsとは、ルーティングについて学ぶ
-
第5回【Next.js】:(補足)サーバーコンポーネントとクライアントコンポーネント
- サーバーコンポーネントとクライアントコンポーネントについて学ぶ
必須なのは記事1~4まででアプリは作れると思っていますが、第5回についても知っておいたほうが良いと思い補足として作成した。
Reactとは
ユーザーインターフェース(UI)を構築するためのJavaScriptライブラリです。
Meta(旧Facebook)が開発し、現在最も人気のあるフロントエンドライブラリではないかと思います。
Reactではコンポーネントという概念が重要になっており、HTMLで配置するボタン、フォーム、テーブルなど表示するまとまりをコンポーネントという部品で定義します。
そうすることで、HTMLのタグのような記述で呼び出して何度でも使えます。
コンポーネントを定義していると仮定して呼び出す例
<HelloButton />
<HelloButton />
<HelloButton />
※jsxファイル内のタグは必ず閉じ括弧が必要。/を記述して閉じ括弧を省略可能
プログラミングで言えば、コンポーネントの定義はクラスで部品を定義するのに似ていて、いくつでもインスタンス化して使えるのに近いと感じました。
開発環境のセットアップ
Reactに関しては環境設定するよりも、React公式ドキュメントでも使っているcodesandboxを使うのが楽。
環境で手間取らずReactのコードに集中できるためcodesandboxを使うのをお勧めする。
方法1)CodeSandboxを使う
右上「+CREATE」ボタンを押す。
「React(JS)」もしくは「React(TS)」を選択するとReactのひな型が作成される。
方法2)ローカルで試す場合
npx create-next-app@latest
実行例
> npx create-next-app@latest
Need to install the following packages:
create-next-app@16.1.6
Ok to proceed? (y) y
√ What is your project named? ... react-test-001
√ Would you like to use the recommended Next.js defaults? » Yes, use recommended defaults
参考:
どちらかの方法でコードを書いていけばよく、続いてReactの基礎的な知識について学んでいきます。
コンポーネントとは
HTMLで配置するボタン、フォーム、テーブルなど表示するまとまりをコンポーネントという部品で定義します。
コンポーネントはJSXという形式のファイルで作成します。
JSXファイルはJavascriptで書かれた関数を定義し、表示したいHTMLをreturnするというもの。
例えばボタンを表示するコンポーネントは下記のようなコードです。
このファイルを「HelloButton.jsx」というようなjsx形式のファイルで保存します。
// Helloと表示するボタンを表示するコンポーネント(HelloButton.jsx)
function HelloButton() {
// ボタンをクリックしたときのメソッド
const handleClick = () => {
alert("Hello, React!");
};
// コンポーネント呼び出し時に出力するHTMLを返す
return <button onClick={handleClick}>Hello Button</button>;
}
export default HelloButton;
コードについて補足:
JSXのHTML内では{}を使うことで変数や関数を埋め込めます。
例:onClick={handleClick}でクリック時の処理を指定
このHelloButtonコンポーネントは呼び出されるとreturn文にある一文を返します。
つまり、
<button onClick={handleClick}>
Hello Button
</button>
というようなHTMLを表示させるという意味を持ちます
コンポーネントの呼び出し
コンポーネントは下記のようにHTMLタグの呼び出しのように使えます。
<HelloButton />
この時気を付けるのはjsxファイル内ではすべて閉じタグが必要だということです。
つまり上記は
<HelloButton></HelloButton>
と書くか、セルフクロージングタグとして
<HelloButton/>
と書きます
app/page.jsxがアプリのルート
<HelloButton />をどこから呼び出すのかというと、アプリのルートであるapp/page.jsxに書いて呼び出します。
app/page.jsxは下記のような感じになります。
// app/page.jsx
import HelloButton from "./HelloButton";
export default function Home() {
return (
<>
<h1>HelloButtonコンポーネントを呼び出す</h1>
<HelloButton />
</>
);
}
<HelloButton />
と書いたところは実際にはreturn文で書いた内容が表示され
<button onClick={handleClick}>
Hello Button
</button>
がブラウザでは表示されます
コードについて補足
JSXが返すHTMLタグは必ず1つの親要素である必要があります。
例えばh1タグとHelloButtonタグを両方をreturnすることはできません。
ただ、それらの親要素として何らかのタグがあればよいので、
divタグで囲うか、意味をもたないタグ<></>(フラグメント)を使う必要があります。
// これはNG
return (
<h1>HelloButtonコンポーネントを呼び出す</h1>
<HelloButton />
);
// これはOK(divタグで複数タグを返す)
return (
<div>
<h1>HelloButtonコンポーネントを呼び出す</h1>
<HelloButton />
</div>
);
// これもOK(フラグメントで複数タグを返す)
return (
<>
<h1>HelloButtonコンポーネントを呼び出す</h1>
<HelloButton />
</>
);
// これもOK(要素が1つだけ)
return (
<HelloButton />
);
※ <>...</>は**Fragment(フラグメント)**と呼ばれ、複数の要素をまとめて返すために使います。JSXでは必ず1つの親要素が必要なため、余計な<div>を作りたくない場合に使用します。
コードは下記のようになります。
参考:
コンポーネントを複数作ったとき構成
画面全体をすべてコンポーネントで構成し、画面全体を表示するコンポーネント(Appコンポーネント)の中に、多数の子コンポーネント(HeaderやFooterなど)を持つような、コンポーネントの中にコンポーネントを配置するような構成を作ってアプリケーションを作成します。
1つのページでのコンポーネントの関係例
App
├── Header
│ ├── Logo
│ └── Navigation
├── MainContent
│ ├── Article
│ ├── Table
│ └── Sidebar
└── Footer
コンポーネント例:
- Appコンポーネント:ルートアプリケーション表示用
- Headerコンポーネント:ヘッダー表示用、Appコンポーネントより呼ばれる
- Logoコンポーネント:ロゴ画像表示用、Headerコンポーネントより呼ばれる
(補足)コンポーネントの種類(関数コンポーネントとクラスコンポーネント)
コンポーネントの書き方として関数コンポーネントとクラスコンポーネントがあります。
関数コンポーネント(最近はこちらの書き方が使われる)
// FunctionHello.jsx
import React from "react";
function FunctionHello() {
return <h1>Hello World!</h1>;
}
export default FunctionHello;
クラスコンポーネント
// ClassHello.jsx
import React, { Component } from "react";
class ClassHello extends Component {
render() {
return <h1>Hello World!</h1>;
}
}
export default ClassHello;
昔はクラスコンポーネントが主に使われ、後年に関数コンポーネントが登場し現在は関数コンポーネントが主流です。
本記事では関数コンポーネントを使います。
exportとimportの基本
コンポーネントのコードを理解するうえで必要なJavascriptの知識にexportとimportがあるのでそれらを説明します。
- export:主に関数を外部のファイルでも使えるようにするためのもの。
- import:別のファイルでexportをした関数を呼び出すためのもの。
例えば下記のようにFunctionHello.jsxで関数をexportすることで、別のファイルでFunctionHello関数を使えるようになります。
// FunctionHello.jsx
import React from "react";
function Hello() {
return <h1>Hello World!</h1>;
}
export default Hello;
別のファイルではファイルをimportに指定することでexportした関数を呼び出せます
import Hello from "./Hello";
export default function Profile() {
return (
<>
<h1>Helloをインポートして呼び出す</h1>
<Hello />
</>
);
}
propsの基本(親→子の受け渡し)
ここでは例えば「親コンポーネントで持っている名前や年齢の情報を、子コンポーネントで表示したい」といった場合に、どうやって値を渡すのかを学びます。
その方法としてはpropsというものを使って値を渡します。
propsとは何か
propsとは親コンポーネントから子コンポーネントに値を渡すのに使うものです。
関数の引数に近いイメージで、子コンポーネントを呼び出す際にHTMLの属性値のように書いて値を渡せます。
ここではAppコンポーネントで定義した名前と年齢をGreetingコンポーネントに渡し、propsを使ってGreetingコンポーネントに値を渡すコードを書いてみました。
propsの渡し方(値)
App.jsx(親コンポーネント(値をpropsで渡す側))
import React from "react";
import Greeting from "./Greeting";
function App() {
return (
<div>
<Greeting name="太郎" age={25} />
<Greeting name="花子" age={30} />
</div>
);
}
export default App;
<Greeting name="太郎" age={25} />というように属性値のような形で値を渡す
propsの受け取り方
値を受け取る場合
Greeting.jsx(子コンポーネント(値をpropsで受け取る側))
function Greeting(props) {
return (
<div>
<h2>こんにちは、{props.name}さん!</h2>
<p>年齢:{props.age}歳です</p>
</div>
);
}
export default Greeting;
受け取るときはprops変数にまとめて渡され、props.nameというような形式で取得できる。
関数を受け取る場合
propsは値だけでなく関数も渡せます。
この例では、handleGreet というalert関数を使って挨拶を行う処理を親のコンポーネントで定義し、それを onGreet というpropsとして子コンポーネントに渡しています。
子コンポーネント側では onClick={props.onGreet} として受け取ることで、関数を子のコンポーネントで実行することができるようになり、ボタンがクリックされたときに親で定義した関数が実行されます。
// 関数を渡す側のコンポーネント
import GreetingFunc from "./GreetingFunction";
export default function App() {
const handleGreet = () => alert("挨拶!");
return (
<div>
<GreetingFunc name="次郎" onGreet={handleGreet} />
</div>
);
}
// 関数を受け取る側のコンポーネント
function GreetingFunc(props) {
return (
<button onClick={props.onGreet}>こんにちは、{props.name}さん!</button>
);
}
export default GreetingFunc;
propsサンプル(値と関数を渡す)
propsについて補足
propsは親から子への一方通行でしか原則渡せないので、複数のコンポーネントに同じ値を渡したい場合は、共通の親コンポーネントでpropsとして渡す値を定義するのがよいです。
(公式: React公式 - Propsを渡す)
次回
次回はReactの重要な機能であるフックについて説明します。
第2回へ
