Reactを使ったテックブログを作成してみた

## はじめに

React学習用のサンプルとして、REST APIを用いたCRUD操作のを用いた技術ブログを作成してみました。

https://github.com/himorishige/techBlog

今回は簡易的に利用できるJSON Serverを使ってデータのやり取りを行っています。アプリケーション内の状態管理にはRedux Toolkit（createAsyncThunk、createEntityAdapter）を利用しました。発展型としては外部サイトに公開できるように外部のデータベースと連携していきたいところです。

#### 記事一覧ページと記事詳細ページ
![スライド1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/04521ca3-d27b-1d76-f1af-2fbea272c6fd.png)
#### 管理画面と記事確認画面
![スライド2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/7e1b7544-a809-7075-4a16-9b0291ce01bc.png)
#### 新規・編集画面
![スライド3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/a7b71a46-5cd6-42f6-daf3-87afe4967997.png)

## 仕様について

今回は下記のような仕様を想定して制作を行いました。

- 閲覧ユーザー向けの機能
  - 記事一覧を表示する（公開設定している記事のみ）
  - 記事詳細を表示する
  - いいねボタンを押すといいねが1増える（何度も押せる）
- 管理ユーザー向けの機能
  - 登録記事一覧を表示する
  - 記事詳細を表示する
  - 記事の編集ができる
  - 記事の公開・非公開の切り替えができる
  - 記事の削除ができる
  - 新規記事の作成ができる
  - 記事はマークダウン記法で登録できる
  - ログイン機能はなし
  - 画像の投稿機能はなし

## 主な利用サービス・利用技術

- React
- Redux Toolkit
- JSON Server … JSONファイルをデータベースとして利用できる簡易APIサーバー
- react-markdown … Reactで使えるマークダウン変換ライブラリ
- styled-components
- TypeScript

## JSON Server

今回外部APIとしてJSON Serverを利用しました。
データベースとしてJSONファイルをそのまま利用することができるので、余計な手間をかけずにすぐに開発に取り掛かることができます。JSON形式のデータを返すAPIであれば、JSON Serverで作成後にURLだけ変えれば外部との連携に簡単に切り替えることもできます。

### セットアップ

```bash
$ yarn add json-server
```

データベースとして利用するJSONファイルを用意します。
フォーマットとしてはリソース名を1階層目に必ず用意しなくてはいけません。
今回はブログサイトを想定していますので下記のようなダミーデータを用意しました。

```json:src/data/db.json
{
  "posts": [
    {
      "id": "1",
      "title": "create-react-app直後にやる環境構築の備忘録",
      "createdAt": 1620804168398,
      "updatedAt": 1621064460898,
      "body": "本文テキスト1",
      "image": "/assets/images/dummy01.jpeg",
      "like": 100,
      "publish": false
    },
    {
      "id": "2",
      "title": "Reactを使ったお天気アプリを作成してみた",
      "createdAt": 1620804168398,
      "updatedAt": 1621070951011,
      "body": "本文テキスト2",
      "image": "/assets/images/dummy01.jpeg",
      "like": 112,
      "publish": true
    }
  ]
}
```

React内で扱う型としては下記を想定しています。
投稿「Post」とその一覧「Post[]」という形です。

```typescript:src/types/index.ts
export type Post = {
  id: string;
  createdAt: number;
  updatedAt?: number;
  title: string;
  body: string;
  image: string;
  like: number;
  publish: boolean;
};

export type Posts = Post[];
```

package.jsonにJSON Server起動用のスクリプトを追記します。

```json:package.json
  "scripts": {
    "json-server": "json-server --watch src/data/db.json -p 3001 -d 2000"
  },
```

`--watch`をつけることで常時監視モードで起動することができます。
Reactがポート3000を利用するため、`-p 3001`として3001番ポートで起動するように変更。
また、`-d 2000`として2秒の待ち時間を入れるようにしています。待ち時間を入れることで非同期のテストも体感的にわかりやすくなのでとても便利です。

```bash
$ yarn json-server
```

![スクリーンショット 2021-05-15 23.03.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/e7b7ef21-6794-6603-d4b8-f291bd00012f.png)
ブラウザで`http://localhost:3001/posts`を開くと登録した記事一覧を表示することができます。

## JSON ServerへのCRUD操作

今回は記事の登録、編集、削除に合わせてRedux ToolkitのcreateAsyncThunk、axiosを利用してJSON Serverへアクセスするようにしています。

```typescript
const post:Post = 記事データ

// 登録 POST
const response = await axios
  .post<Post>(`${URL}/posts`, post)
  .catch((err) => {
    // エラー処理
  });
return response.data;

// 編集 PUT
const response = await axios
  .put<Post>(`${URL}/posts/${post.id}`, post)
  .catch((err) => {
    // エラー処理
  });
return response.data;

// 削除 DELETE
const response = await axios
  .delete<Post>(`${URL}/posts/${post.id}`, {
    data: { id: post.id },
  })
  .catch((err) => {
    // エラー処理
  });
return response.data;
```

上記は省略していますが前後の処理については下記ソースを参照いただければと思います。

https://github.com/himorishige/techBlog/blob/main/src/features/posts/postsEntitySlice.ts

## Redux Toolkit

JSON Serverからデータの取得にはcreateAsyncThunkを経由して、createEntityAdapterを使い処理を行っています。
詳細は下記にも記事を投稿させていただきました。

https://qiita.com/himorishige/items/1a9735416c8861a6fbf7

## 今後の拡張

今後の拡張としては下記を想定すると外部公開用のテックブログの完成です。

- 管理画面の認証機能
- 画像の投稿機能
- Express、mongoDBを用いたバックエンド構築（DBは好みで）

# さいごに

チュートリアル的なTODOアプリからちょっと進んだ？、APIを用いたCRUDなアプリケーションを作成することでより知識を深めることができると思います。JSON Serverで気軽にAPIを構築できるのでぜひ試してみてください。

# 関連記事

https://github.com/himorishige/techBlog

https://qiita.com/himorishige/items/1a9735416c8861a6fbf7

# 参考サイト

React

https://github.com/reduxjs/cra-template-redux-typescript

JSON Server

https://github.com/typicode/json-server

https://www.codegrid.net/articles/2017-json-server-1/

Redux

https://www.youtube.com/watch?v=Lmtr8hmXvj4&list=PLtbitg0evatjxN_BhyJO124bV2eDoJumf

https://www.youtube.com/watch?v=yQz2gSQiOZA&list=PLtbitg0evatg24WZm9Q8wTIP-We2V0OpZ

https://www.cyokodog.net/blog/redux-toolkit-async-thunk/

https://redux-toolkit.js.org/api/createAsyncThunk

https://redux-toolkit.js.org/api/createEntityAdapter