【React入門】絶対に躓かないReact（Next.js 13）ワークショップ #1

# :beginner: はじめに
この記事は、これからReactを学びたい方向けに書かれています。
複数記事の構成になっているので、#1から始めることを推奨します。

また、Reactが初めてであれば、環境構築なしでReactについて学べる以下の記事から始めると、
より躓かずに進められるかと思います！

https://qiita.com/kwc_dev2/items/8927a149056f3e66dbf0

Reactの公式チュートリアルがCreat React Appからフレームワーク推奨になったことを受け、
Next.js 13を利用してReactを学んでいきます。

# :round_pushpin: 本ワークショップのゴール

## :pencil: 学べる内容　(進捗次第で変わる可能性があります...)
1. **Next.jsの環境構築 && コンポーネントについて**　**:point_left: 今ここ**
1. [アトミックデザインとHooksの基礎](https://qiita.com/daiti0113/items/2efd0e9ae774b3db61aa)
1. API呼び出し(Fetch API)
1. スタイリング(Tailwind CSS)

:::note warn
Reactを中心に学んでいく内容となっているので、Next.jsの機能にはあまり触れません。
:::

## :calendar_spiral: 最終的な成果物

**沖縄で開催されるエンジニアイベント一覧**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527043/657c3729-23b3-1440-30ad-004117c26ca4.png)
ConnpassのAPIを利用して、沖縄で開催されるイベント情報を取得し、カードUIで表示します。
筆者が沖縄出身であるため「沖縄」にしていますが、絞り込み条件は好みに合わせて後ほど変更してください:grin:

# :earth_asia: 環境について
必ず以下がインストールされていることを確認してから進んでください。
Mac/Linuxの環境を想定しているため、Windowsの場合はWSLやDockerで環境構築を行ってください。
環境構築の方法については、各自ググってください:wink:

- `Node.js` == `v18.13.0`
- `yarn` == `v1.22.19`

## Node.jsのインストール

以下の記事を参考に、`anyenv`, `nodenv`を利用してインストールすることをおすすめします。

**Macの方はこちら**

https://qiita.com/kyosuke5_20/items/eece817eb283fc9d214f

**Windowsの方はこちら**

https://zenn.dev/yuta_ura/articles/70fad750703d41

以下のコマンドの結果が同じになれば問題ありません。

```zsh
% node -v           
v18.13.0
```

## Yarnのインストール

Next.jsではデフォルトのパッケージ管理システムに[Yarn](https://chore-update--yarnpkg.netlify.app/ja/)を採用しています。

以下の手順に従ってnpm経由でインストールします。

https://chore-update--yarnpkg.netlify.app/ja/docs/install

こちらも、以下のコマンドの結果が同じになれば問題ありません。

```zsh
% yarn -v
1.22.19
```

# #1 Next.jsの環境構築 && コンポーネントについて

### Next.jsのチュートリアルに従ってサンプルアプリを起動する

1. [Next.jsの公式チュートリアル](https://nextjs.org/learn/basics/create-nextjs-app)に沿ってサンプルプロジェクトを作成する

    ```zsh
    npx create-next-app@latest
    ```

    ```zsh:実行結果
    # プロジェクト名以外はデフォルトの選択肢を選んでいます。エンターだけで大丈夫です。
    ✔ What is your project named? … react-workshop
    ✔ Would you like to use TypeScript with this project? … Yes
    ✔ Would you like to use ESLint with this project? … Yes
    ✔ Would you like to use Tailwind CSS with this project? … Yes
    ✔ Would you like to use `src/` directory with this project? … No
    ✔ Use App Router (recommended)? … Yes
    ✔ Would you like to customize the default import alias? … No
    ```


1. アプリを起動する

    ```zsh
    cd react-workshop
    ```

    ```zsh
    yarn dev
    ```

    :::note
    以下のような出力結果になればOK。
    ```zsh
    $ next dev
    - ready started server on 0.0.0.0:3000, url: http://localhost:3000
    - event compiled client and server successfully in 236 ms (20 modules)
    - wait compiling...
    - event compiled client and server successfully in 161 ms (20 modules)
    - wait compiling /_error (client and server)...
    - event compiled client and server successfully in 1166 ms (161 modules)
    - warn Fast Refresh had to perform a full reload. Read more: https://nextjs.org/docs/messages/fast-refresh-reload
    - wait compiling /favicon.ico/route (client and server)...
    - event compiled successfully in 373 ms (99 modules)
    ```

    http://localhost:3000 にアクセスして、アプリが表示されることを確認する。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527043/2346bbac-d584-adfb-d12a-f07852592591.png)


### サンプルページを変更してみる

`app/page.tsx`を開き、ロゴ画像を`<h1></h1>`タグで囲み、ロゴ画像の前に **Learn React with** を付け足してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527043/7862dd0f-ae3d-cb8a-0258-1e9b94eb412d.png)


```tsx:app/page.tsx
import Image from 'next/image'

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      {/* 省略 */}
      <div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px]">
        {/* 32行目あたりの`<Image>`タグを`<h1>`タグで囲み、中に「Learn React with」を付け足します。 */}
        <h1>Learn React with
          <Image
            className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
            src="/next.svg"
            alt="Next.js Logo"
            width={180}
            height={37}
            priority
          />
        </h1>
      </div>
      {/* 省略 */}
  )
}
```


http://localhost:3000 にアクセスし、
以下のように、「Learn React with」が表示されていればOKです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527043/0f856a27-84d6-41ec-0b7c-b504d6914f7a.png)

:::note
`git`が使える方はここでコミットしておくことをおすすめします。
:::

### ページを追加する

イベント一覧を表示するためのページを追加していきます。
Next.jsではディレクトリ構造に基づいてルート(URLのパス)が生成されます。
今回は、`/events/list`にイベント一覧画面を表示させたいので、
`app`ディレクトリの配下に、`app/events/list/page.tsx`となるようファイルを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527043/5e7c4119-9c84-f0ca-3851-98817437ac56.png)

`app/events/list/page.tsx`には、以下のコードを書いておきます。
Reactでは以下のようなHTML要素を返すような関数を **コンポーネント** と呼びます。
厳密にはHTMLとは異なり、JSの中でHTMLのようにマークアップができるこの記法を **JSX** と呼びます。
細かな違いは後ほど紹介するので、ここではHTMLを返す関数をコンポーネントと呼ぶんだなと覚えておいてください。

```tsx:app/events/list/page.tsx
export default function EventList() {
  return (
    <div>
      <h1>イベント一覧</h1>
    </div>
  )
}

```

以下のように、http://localhost:3000/events/list にアクセスし、イベント一覧画面が表示されればOKです :ok_hand:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527043/53233aff-042d-e00a-3519-7146bb708a68.png)



# #1 まとめ

**#1 Next.jsの環境構築 && コンポーネントについて** では、
Next.js のアプリケーションを起動し、ページを追加しました。
少ない内容ではありますが、コンポーネントについて知っていただければ幸いです。
次回以降は、実際に画面を構成するためのコンポーネントを大量に作っていきます。

[#2 アトミックデザインとHooksの基礎へ進む](https://qiita.com/daiti0113/items/2efd0e9ae774b3db61aa):running::dash: