React to nest

ReactとNestでWebアプリケーションを作る3回目です。 最初からやりたい場合はナビゲーションから初回を開いてください。

今回はフロントエンドのReactとサーバサイドのNestをつないでいきます。

まずは最初に、ReactとNestを別のポートで動くようにします。 ポートとはそのPCでのネットワークの受付番号です。番号によって、どのアプリケーションがその通信を受け取るか区別しています。 今、ReactとNestは両方とも3000ポートを利用しています。このままだとどちらが3000番の通信を受け取ればいいのか判別できないので、両方とも同時に立ち上げることはできません。 今回はNestを3000ポートから3001に変更します。

myreactapp/server/src/main.tsを以下のように変更します。

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3001); // 3000→3001にしました。
}
bootstrap();

ターミナルで以下を実行します。

npm run watch:server

http://localhost:3001 にアクセスして「Hello World! そして世界へ」と表示されれば成功です。 表示されたらCtrl+Cでサーバを停止しておいてください。

続きまして、ReactとNestをつなげていきます。 Reactにアクセスしてなにもすることがない場合、Nestに通信を回すということをします。

myreactapp/front/package.jsonを以下のように修正します。 package.jsonの一番最後の部分です。

  ,"proxy":"http://localhost:3001" (←もともとある一番最後のカッコの前に、この行を追加します。)
} (←もともとある一番最後のカッコです。)

次に、ReactとNestを同時に起動するようにします。 ターミナルでmyreactappディレクトリで以下のコマンドを実行します。

npm i npm-run-all

myreactapp/package.jsonを変更します。

{
  "name": "myreactapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    ,"watch:client": "npm start --prefix front"
    ,"watch:server": "npm run start:dev --prefix server"
    ,"watch": "run-p watch:**" (←この行を追加します。)
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "npm-run-all": "^4.1.5"
  }
}

これで、一度のコマンドでReactとNestを起動できるようになりました。

コマンドを実行しておきます。

npm run watch

これでReactとNestが立ち上がりました。

次に、Nestのメッセージを受け取るURLを変更します。 myreactapp/server/src/app.controller.ts を変更します。

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get("/hello") // このようにこの行の@Get()の中に"/hello" と入れます。
  getHello(): string {
    return this.appService.getHello();
  }
}

これで、http://localhost:3001/hello にブラウザでアクセスすると、「Hello World! そして世界」と表示されるようになりました。

次に、ReactからNestに通信します。

myreactapp/front/src/App.tsxを以下のように変更してください。

import React, { useState } from 'react'; // この行を変更
import logo from './logo.svg';
import './App.css';

function App() {

  const [message, setMessage] = useState("ロード中...");// この行を追加

  (async () => {// ここから
    const response = await fetch('/hello', { method: 'GET' });
    setMessage(await response.text());
  })(); //この行までを追加

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <p>作ったった</p>
        <p>{message}</p> {/* この行(</p>まで)を追加 */}
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

これでReactにNestの情報を渡して画面表示ができるようになりました。 http://localhost:3000にアクセスしてください。

ReactにNestレスポンスを表示

このようにNestで出力した「Hello World! そして世界」という文字がReactに表示されていれば成功です。

少し、コードの解説をします。

import React, { useState } from 'react'; // この行を変更

では、reactのライブラリ群から、デフォルトの内容をReactとして取得、また、useStateを取得しています。

  const [message, setMessage] = useState("ロード中...");// この行を追加

では、messageという値を画面で使えるように準備しています。 Nest=サーバから取得して表示するため、画面表示できるタイミングよりちょっと遅れて描画されなければなりません。 よって、デフォルトの内容を"ロード中"として。messageが取得できたら、messageを差し替えるためにsetMessageという変数をuseState()という関数を実行することで取得しています。

  (async () => {// ここから
    const response = await fetch('/hello', { method: 'GET' });
    setMessage(await response.text());
  })(); //この行までを追加

この4行は関数を定義して、即座に実行しています。非同期型=asyncな関数を実行するための1つの方法です。 (async()=>{})で関数を作って、その後の一番最後の () で実行しています。

その中の2行でサーバから値を取得しています。 fetch関数でNestの/helloにアクセスしてresponseを得ています。 response.text()でサーバからの値を文字列として取得できるので、setMessage()に渡してmessageに変更があったことをReactに伝え、画面表示をしています。

これで、ReactとNestをつなぐことができました。

続いてはNestでデータベースにデータを保存できるようにしていきます。