React、json-server、http-proxy-middlewareで疑似バックエンドと通信

フロントエンド開発初期段階ではバックエンドがいないため、疑似的なバックエンドを用意したくなります。
React、json-server、http-proxy-middlewareの組み合わせで、疑似バックエンドとの通信をテストしたときのメモです。localhostでjson-serverを動かしています。

# やりたいこと
・全ユーザ取得
　　→　/service/api/userにget
・名前、年齢を入力し、addボタンを押すと、json-serverにユーザ登録
　　→　/service/api/userにpost
・ラジオボタンでユーザを選択し、deleteボタンを押すと、json-serverからユーザ削除
　　→　/service/api/user/:idにdelete
・json-serverから応答を待っている間はloading...を表示
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/fd931956-81ab-4e64-ba8b-772bdf48ecdd.jpeg)

# json-serverについて
json-serverを動かすためにソースコードを書く必要はありません。データを格納するdb.json、パス設定のroutes.jsonを用意するだけになります。
db.jsonは、存在しない場合はjson-server起動時に自動で下記が作成されます。
```:デフォルトのdb.json
{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}
```
この状態でhttp://localhost:port/posts/1 にgetすると下記が返ってきます。
```:getの結果
{ "id": 1, "title": "json-server", "author": "typicode" }
```
http://localhost:port/posts/ にgetした場合はpostsの全データが返ってきます。
配列データの場合はidが必須になっています。
```:httpメソッド
GET    /posts　→全取得
GET    /posts/1　→指定したidだけ取得
POST   /posts　→追加
PUT    /posts/1　→指定したidを変更
PATCH  /posts/1　→指定したidの一部更新？
DELETE /posts/1　→指定したidを削除
```
今回はget, post, deleteだけ使いました。

# json-serverの設定
インストール
```
npm install json-server
```
初期状態ではdb.jsonは空にしました。
```:db.json
{
  "user": []
}
```
json-serverはパスに"/"があっても認識してくれないため、下記のようにパスの変換をする必要があります。
ここの"/user"は、上記db.jsonの"user"と名前を一致させる必要があります。
```:routes.json
{
	"/service/api/user": "/user",
	"/service/api/user/:id": "/user/:id"
}
```
db.jsonとroutes.jsonをReactのルートディレクトリに格納します。
```
 /
 +public/
 +src/
 |
 +db.json
 +routes.json
 +package.json
```
下記のようにpackage.jsonに起動処理を追加します。
```:package.jsonのscriptsに追加
"json-server": "json-server --watch db.json --routes routes.json --port 5000"
```
もしdelayをさせたい場合は--delay 1000のようにオプションを指定します。

json-serverの起動は下記です。
```:json-server起動
npm run json-server
```

# http-proxy-middleware
Reactが/service/api/userにアクセスしようとしてもReact Routerが受け取ってしまうので、proxyを立てて、proxyがjson-serverに転送するようにします。
今回はhttp-proxy-middlewareを使いました。

インストール
```
npm install http-proxy-middleware
```

setupProxy.jsを/src直下に格納します。
```
 /
 +public/
 +src/
 |   +setupProxy.js
 |
 +db.json
 +routes.json
 +package.json
```
json-server起動時に指定したポート5000を設定します。
これでReactが/service/apiにアクセスするとjson-serverに転送されます。
```:setupProxy.js
module.exports = function (app) {
  app.use(
    createProxyMiddleware(
        ["/service/api"],
      {
        target: "http://localhost:5000",
        changeOrigin: true,
      }
    )
  );
  app.listen(3000);
};
```
なお、npm run build、serve -s buildした場合はhttp-proxy-middlewareは動きませんので、特にコード修正することなく、本番環境ではproxyなしで動作できます。

# 動作させる
ユーザを追加していくとdb.jsonにユーザが追加されていきました。
```:db.json
{
  "user": [
    {
      "name": "Taro",
      "age": 30,
      "id": 1
    },
    {
      "name": "Hiroko",
      "age": 20,
      "id": 2
    },
    {
      "name": "Koichi",
      "age": 40,
      "id": 3
    },
    {
      "name": "Hide",
      "age": 21,
      "id": 4
    }
  ]
}
```
また、json-server起動時に--delay 2000のようにすることでレスポンスを遅くし、レスポンスが遅い場合にloading...が表示されることも確認できました。

全体図
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/3f6478db-79ac-0850-ea31-f6ab8479b953.jpeg)


[ソース](https://github.com/gomagon/react-jsonserver-test)

# 参考
[https://blog.codecamp.jp/json-server-beginner](https://blog.codecamp.jp/json-server-beginner)