今回は前回Udemyの動画でReact及びNext.jsを使った環境構築のやり方を学んだので
ASP.NETでReactのNext.jsを使った初期画面の構築を行いたいと思います。
Udemy動画でReactを学んだ動画は以下を参照
上記を学んでいれば環境構築は問題ありませんが、もしやっていない場合、Node.jsを事前にインストールしておいてください。(npmコマンドなどを使います)
インストールされているか確かめるのはVS上のターミナルかPowerShellでnodeと入力すればOKです。
ここではNode.jsの説明は割愛致します。
目次
環境構築
プロジェクトでReact.jsでのASP.NET Core
最初の新規プロジェクトでReact.jsでのASP.NET Coreを選択
参考サイトを参考に環境を構築
以下の参考サイトを利用すると環境構築できます。ただ、少し違う所があるので後述にあげておきます。
Visual Studio 2019で 最新の React(Next.js) + TypeScript + ASP.NET Core を簡単に構築
- 今回はNode.jsを使った環境構築をしているため、yarn でなく npmを使っている
- 3.のTypeScriptを入れるかどうかを十字キーの左右で入れ替える
- 6.Startup クラスは.NET6ではProgram.csに統合されているため対応方法が違う
- 7はnpmを使用する場合は対応不要。Package.jsonによって npm devはnext devなど、Next.jsを使ったものに書き替わるため。
- 8.の起動するの所はVisual Stdioの実行ボタンでOK
- 3.のTypeScriptは指定しなくてもOK
Startup クラスは.NET6ではProgram.csに統合されているため対応方法が違う
こちらに関しては下記記事を参照してください。.NET 6 ではCore 3.1 と違って、StartUp.csが存在しません。
まず、事前にNugetパッケージマネージャーで下記をいれてください。
・Numind.AspNetCore.SpaServices.Extensions(Microsoft.AspNetCore.SpaProxyも自動でインストールされる)
そしてProgram.csに上記を足します。
省略 ・ ・ ・ // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseSpa(spa => { spa.UseProxyToSpaDevelopmentServer("http://localhost:3000"); }); app.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); app.MapFallbackToFile("index.html"); ; app.Run();
ただ、これだけだとダメで.csprojのSpaProxyServerUrlとSpaProxyLaunchCommandも変更します。(npm startだとビルドしてないと立ち上がらないため)
プロジェクト名.csproj
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <IsPackable>false</IsPackable> <SpaRoot>ClientApp\</SpaRoot> <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes> <SpaProxyServerUrl>http://localhost:3000</SpaProxyServerUrl> <SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup>
起動
上記が終わったら VSのデバッグ開始ボタンを押して下記のようなスタート画面が表示されたらそのURLにアクセスすれば初期画面が立ち上がります。
React.jsでMVCを実現(Next.js未使用)
React(npx create-react-app xxxx で作り直した時は後述の通りReactプロジェクト初期状態のファイルの一部が必要)の場合は既存のControllerに入っているweatherforecastを参照できたのでMVCの形式でも問題なさそうです。
ただ、その後画面への表示を試みたのですが、
ncaught (in promise) SyntaxError: Unexpected token ‘<‘, “<!DOCTYPE “… is not valid JSON
のエラーに悩まされ、解決できず断念・・・。他サイトを見たのですが問題解決に至らず。といった感じです。
↑上記エラーですが、Reactプロジェクト初期状態で存在していたsetupProxy.jsを入れたら解決できました。(それ以外ではpackage.json(http-proxy-middlewareを入れる)/aspnetcore-react.js/aspnetcore-https.jsもReactプロジェクト初期状態のソースから移動)
const { createProxyMiddleware } = require('http-proxy-middleware'); const { env } = require('process'); const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:11038'; const context = [ "/weatherforecast", "/home", ← この後の説明で必要なので追加 ]; module.exports = function(app) { const appProxy = createProxyMiddleware(context, { target: target, secure: false, headers: { Connection: 'Keep-Alive' } }); app.use(appProxy); };
SQLServerの使用
今回のサーバーサイドは過去記事に習って作成しておりますので省略します。今回は↓の記事のサーバサイド側から今回用に変えた箇所を表示します。
HomeController.cs(HttpGetの所だけ下記のように変更)
// GET: Article [HttpGet] public IEnumerable<TestDb> Get() { return _context.TestDb.ToArray(); }
以降はReact側を変更
以降はReactプロジェクト初期状態のソースのようにfetchを使えばアクセスすることができます。今回はReactの記法に乗っ取り、一回だけ自動で呼ばれるように作成したuseEffectを使って情報を取得し、useStateに格納したものをコンポーネントであるBodyに対してpropsを渡して表示させました。
フォルダ構成
ClientApp/src/App.js
import './App.css'; import { useState, useEffect } from 'react'; import Body from "./Components/body"; function App() { const [ articles, setArticles] = useState([]); useEffect(() => { const getArticles = async () => { const result = await fetch('home').then(res => res.json()); setArticles( result ); }; getArticles(); }, []); return ( <> <Body articles={articles} /> </> ); } export default App;
ClientApp/Components/body.js
import React from 'react'; const Body = ({ articles }) => { if (!articles) { return <div>データがありません</div> } return ( <div className="App"> <table className='table table-striped' aria-labelledby="tabelLabel"> <thead> <tr> <th>ID</th> <th>Descrition</th> <th>UpdateTime</th> </tr> </thead> <tbody> {articles.map((article) => ( <tr key={article.id}> <td>{article.id}</td> <td>{article.test}</td> <td>{article.update_Time}</td> </tr> ))} </tbody> </table> </div> ); }; export default Body;
実行結果
今回はReact.jsを使ってSQLServerの内容を表示することができました。
Next.jsだとMVCの型にはできなさそう
ただ、Next.jsを使った場合はReactの時に参照できていたControllerが参照できなかったです。
Next.jsのAPIから自サーバにアクセスしてもDBの値が取得できないのでMVCの型が破綻してしまってました。Next.jsには別途:next.config.js/jsconfig.jsonというファイルがあるのでpackage.jsonではなく、上記をいじるのかもしれませんが今の所原因が不明です。
先ほど、React側で行った、Fetchに変更しての取得も試みましたがやはりうまくいきませんでした。(404が返っている)
色々調べましたがやはりNext.jsの記述は少なく、MVCの型での表示は失敗しました。
もしASP.NETでNEXT.jsを使いたいなら、フロント側とバックエンド側で使用サーバを分けるしかなさそうです。React.jsならMVCの型でも問題なく動作させることができます。