Next.js 入門メモ


どこを抑えたらよいか、どう書けばよいかをさらっと解説します。

# Next.jsとは
Reactというライブラリをほぼ完全にサポートしていて、上位互換のようなイメージです。
Reactはビルド(コンパイル)すると大量のJSを生成します。私たちがページにアクセスすると返されるのは少量のHTMLと大量のJSが返されます。そこからJSをでレンダリングなどの処理を行います。クライアントで処理するので**Client Side Rendering**(CSR)といいます。( ≒ SPA)初回レンダリングこそ遅いものの、ページ間の移動は非常に高速です。

Next.jsはReactで記述できるのですが、ビルドするとHTMLとJSを生成します。私たちがページにアクセスすると返されるのはHTMLとJSです。HTMLがそこそこ書かれているため読み込みがJSでレンダリングするより圧倒的に高速です。
HTMLを表示させてからJSでレンダリングや読み込みを行うので真っ白の画面で待たせる時間が非常に短くなり、ユーザーの体験が向上します。
サーバーサイドでJSをレンダリングしておくので、**Server Side Rendering**(SSR)と言ったりします。
また、GoogleFontsをビルド時点で取得して先にレンダリングを済ませておくなどもできます。これを**Static Site Generator**(SSG)
といいます。
Next.jsはSSRとSSGの両方の恩恵を受けることができます。

一言でまとめるとReactの上位互換でレンダリングも早いという感じです。

# 準備
必要なもの
* Node.js
* ブラウザ
* yarn (npmでもいい)

です。

個人的にはNode.jsはバージョンによるエラーが多いので`NVM`のインストールをおすすめします。
* NVMのインストール
```sh:Terminal
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
source ~/.bashrc
```
インストールを行い、
```sh:Terminal
nvm install stable
npm i -g yarn
```
で`yarn`が使用できます。

# プロジェクト作成
```sh:Terminal
yarn create next-app
```
Project名が聞かれるので**先頭小文字**入力してください。`TypeScript`と`ESLint`を使用するか聞かれるのでどちらか選択してください。ESLintは入れておいたほうがいいと思います。
```sh:Terminal
✔ Would you like to use TypeScript with this project? … No / Yes
✔ Would you like to use ESLint with this project? … No / Yes
```
あとは放置で下のメッセージが出ればOKです。
```sh:Terminal
Success! Created test at /home/**********/Project名
```

### 頻出コマンド
| 説明 | コマンド |
|:-:|:-:|
| サーバーの起動  | yarn dev  |
| ライブラリのインストール | yarn add [packege]|
| 依存関係のインストール | yarn |

は覚えておきましょう。

## 作成していく上で準備

**`index.tsx` / `globals.css`は中身すべて消去
`Home.module.css` はファイルを消去**
しましょう。

## 先にまとめ
**関数のreturnのところにHTMLがかける！
その中でJSを使い時は波括弧で囲むとHTMLの中でJSがかける！
その関数をコンポーネントという一つのまとまりにして使いまわしたりできる！**

**Propsというものを使えばファイル同士で値を渡すことができる！
Hooksという超便利な機能がある！**

## JSXの書き方
クラスコンポーネントはあまり使用されないので関数コンポーネントで記述します。
```react:index.html
const Home = () => { // Homeという関数コンポーネント
    return ( // return 以下でHTMLライクに記述することができます。
        <>Hello World!</>
    )
};

export default Home;
```
`<></>`とは、React Fragmentといい、コンポーネント一つに２つ以上の親要素を持ってはいけません。そのためdivでラッピングしてもいいのですが、marginやpaddingなど余計についてしまうのを防ぐため、`<></>`で覆います。

```sh:Terminal
yarn dev
```
して**http://localhost:3000** にアクセスすると実際にHello World!が表示されたと思います。

## コンポーネントを他のファイルで使用したいとき
例えばindex.tsxを他のファイルで使いたい場合
```react:test.tsx
import Home from "."

const Test = () => {
    return (
        <Home />
    )
}

export default Test;
```
と記述することでコンポーネントをimportすることができます。

## Props
Propsとは親から子に値を渡したいときに使用します。
例えるならコンポーネントに引数をもたせるイメージです。
```react:例
<Home text={"テキスト"}>
```
こんな感じです。

**子**のコンポーネント
```react:child.tsx
const Child = (props: {text : string}) => { //TSのときはここに型を書きます。
    const {text} = props; // 分割代入
    
    return (
        <h1>{text}</h1>
    )
}

export default Child;
```
ここでポイントは関数コンポーネントの引数のところにpropsを書くことでpropsを受け取ることができます。

また、受け取った変数をJSXで使用したい場合はreturnの中で`{}`この波括弧を使用します。**波括弧の中であればHTMLの中にJSを記述することができます。**

**親**のコンポーネント

```react:parent.tsx
import Child from "./child"

const Parent = () => {
    return (
        <Child text={"こんにちは"} />
    )
}

export default Parent;
```

これでChildコンポーネントに値を渡すことができました。

### なくてもいいProps
渡しても渡さなくてもいいPropsにしたいとき
**子**のコンポーネント
```react:child.tsx
const Child = (props: {text? : string}) => { // ? をつけます。
    const {text} = props;
    
    return (
        <h1>{text}</h1>
    )
}

export default Child;
```
にするとOKです。

## Hooks
HooksとはReactの機能の一つです。

useState, useEffect, useContext, useReducer, useRef などあります。
ここで、**useState と useEffect**を覚えたらとりあえずOKです。

語弊がありますがとてもざっくり解説します。
| Hooks | 説明 |
|:-:|:-:|
|  useState | 値の保持  |
| useEffect  |  非同期で実行できるて発火のタイミングを決めれる |
| useContext| ファイル間で値を共有 |
| useReducer  |  useStateに関数がついたバージョン |
| useRef  |  inputタグなどの値が取得できる |

詳しくは[フック API リファレンス](https://ja.reactjs.org/docs/hooks-reference.html)を確認してください。

### useStateの使い方
```react
const [呼び出し値, 更新する関数] = useState<型>(初期値);
```
使い方はこんな感じです。
```react
const [text, setText] = useState<string>("テスト");

console.log(text) // テスト

setText("こんにちは");

console.log(text) // こんにちは
```
実際に使ってみます。

```react:index.html
import { useState } from "react";

const Home = () => {
    const [inputText, setInputText] = useState<string>("");

    return (
        <>
            <input type="text" onChange={(e) => setInputText(e.target.value)}/>
        </>
    )
};

export default Home;
```
これで入力したらinputTextに値が保持されていきます。
あとはAPIで値を渡したりするときなどに使い回せます。

### useEffectの使い方

```react
useEffect(() => {
    非同期で実行したい処理
},[発火させるための変数])
```
第２引数の配列の中に更新させるための変数を入れます。
つまり、**配列の中にある値に変化が起こるとuseEffectは発火します。**
APIなどの処理に非常に最適です。

発火タイミングは
初回ロード時と配列が変化したときです。

また、useLayoutEffectというのもあるのですが、違いは
useEffectはレンダリングしながら実行するのに対して
useLayoutEffectは実行が終わってからレンダリングを開始します。
基本的にはuseEffectでOKだと思います。

axiosというライブラリを使用します。中身は少し適当です。
```react:例
import { useState, useEffect } from "react";
import axios from "axios";

const Home = () => {
    const [inputText, setInputText] = useState<string>("");
    const [response, setResponse] = useState<object|null>();

    useEffect(() => {
        axios.get("https://*******************")
            .then((res) => setResponse(res.data) // APIを飛ばして帰ってきた値をuseStateに保持します。
            .catch(err => console.log(err))); //エラーのときはlogを出力します。
    },[setInputText]); // 文字列を入力するたびにuseEffectが走ります。

    return (
        <>
            <input type="text" onChange={(e) => setInputText(e.target.value)}/>
        </>
    )
};

export default Home;
```
これさえわかればNext.js(React)はある程度かけます。

## その他
この先の軽い道標になればと思います。
* ボタンクリックしたら遷移したい。
 aタグではなくNext.jsがLinkタグを用意してくれているのでそれを使用しましょう。高速に遷移できます。
* 関数で遷移させたい。
 window.location.hrefではなくuseRouterを使いましょう。
* ページ遷移先で値がほしい。(遷移するときに値も持っていきたい。)
  useRouterにqueryがあるのでそれで受け渡しできます。
* window is not definedとかでるんだけど...
    if (process.browser)で囲えば一旦回避できます。SSRのため、windowオブジェクトが存在しないためです。これを使えばCSRに実行できます。もしくはuseEffectで実行すればCSRになります。
* JSXで条件分岐がしたい。
  三項演算子を使うことをおすすめします。ifも使えます。
* 配列をjsxで表示させたい。
  mapメソッドを使用するといい感じに表示できます。
* デプロイはどうしたらいい
  Vercelなどで簡単にデプロイできます。
* コンポーネントの使い方がわからない。
  Atomic Designで検索してみると良いと思います。
* buildしたい。
  packege.jsonにbuildを記述して
```jsonc:packege.json
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "build" : "next build && next export" // 追加
  }
```
```sh:Terminal
yarn build
```
したらOKです。

Next.jsは非常に使い勝手がいいです。JSも少しわかっていれば書くことができます。
敷居もそんなに高くないのでぜひ一度お試しください。

最後まで読んでいただきありがとうございました。