マツダコウヘイ @matskohe

PhyloCOG

Published on
投稿日: 2021-03-18
lastPublished on:
最終更新日: 2022-08-10

経緯

知人(ポスドク )から依頼有り。next.jsの動的ルーティングの勉強になると思い挑戦。

PhyloCOGとは

COG(タンパク質)の進化情報と系統樹のデータ参照webページ。知人らの研究に便利だそう。

完成物

構成

system_pic

データベース: Mongo DB Atlas

フレームワーク: next.js(SSG)

この構成にした理由

  • これからデータベースの設定が変わる可能性あり。MongoDB(noSQL)は拡張や変更がRDBより簡単。
  • 項目の読み込みがメインなので、RDB(mysqlやpostgresql)よりもはやい。
  • mongoDB atlasの利用が無料の範囲内でおさまりそう。
  • 公式docや、ブログ記事next.is公式のexampleが有りわかりやすい。

苦戦したポイント

①next.js(getStaticPaths)⇄MongoDBの接続。

mongodb 3.6.4だと

(node:80793) Warning: Accessing non-existent property 'MongoError' of module exports inside circular dependency

エラーがでるので3.6.3を使用。Mongoclientでの接続、データの取得のコードに問題があると思って、時間をとってしまった・・・。

②動的なルーティングの静的生成方法


動的なルーティングの静的生成をする場合は、getStaticPathsとgetStaticPropsを使います。(動的なルーティング無しのただの静的生成の場合は、getStaticPropsだけでokです。)

流れは以下。
①getStaticPathsでルーティングの値を全部取得し、その情報1つ1つにparamsプロパティをつけます。map関数など使います。
②getStaticPathsで取得したparams付いた値を、getStaticPropsに代入し、そのページで表示する情報を取得し、propsをつけます。
③getStaticPropsで取得したpropsがついた値を、○○(ページを表示する関数なり変数)で取得し、表示。

実際のコードは以下。

export async function getStaticPaths() {
const client = new MongoClient(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
if (!client.isConnected()) await client.connect();
const res = await client
.db(process.env.MONGODB_DB)
.collection("additionaltable3_cogs_corrected")
.find({})
.project({ cog_id: 1, _id: 0 })
.toArray();

if (client.isConnected()) client.close();

const paths = res.map((copiedCog) => ({
params: { cogid: copiedCog.cog_id.toString() },
}));
return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
const client = new MongoClient(MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});

if (!client.isConnected()) await client.connect();
const resp = await client
.db(MONGODB_DB)
.collection("additionaltable3_cogs_corrected")
.findOne({ cog_id: params.cogid });
if (client.isConnected()) client.close();

const cogData = await JSON.parse(JSON.stringify(resp));
return { props: { cogData } };
}


③検索フォームの値でページ遷移


流れとしては、
①検索フォームに変更があったとき(onChange)、フォームの値をuse stateでキープ。
②searchボタンを押した時(onSubmit)に、デフォルトの動作を止め、use stateでキープした値とnext/routerを使ってページ遷移。

といったかんじ。コードは以下。

import { useState } from "react";
import { useRouter } from "next/router";

const preventDefault = (f) => (e) => {
e.preventDefault();
f(e);
};

export const NumberSearch = ({}) => {
const [cogNum, setCogNum] = useState("/");
const router = useRouter();

const handleParam = (setValue) => (e) => setValue(e.target.value);

const handleSubmit = preventDefault(() => {
router.push({
pathname: "/[cogid]",
query: { cogid: cogNum },
});
});
return (
<>
<div>
<form
onSubmit={handleSubmit}
>
<p>Input COG Number</p>
<label>
COG
<input1
type="text"
name="cogNum"
placeholder="0001~5665"
onChange={handleParam(setCogNum)}
required
/>
</label>
<input type="submit" value="Search PhyloCOG"/>
</form>
</div>
</>
);
};

普通*のページ遷移をする場合はnext/linkを使いますが、ユーザーの入力によって遷移先が変わる検索フォームを使う場合は、next/routerを使います。

githubで公開しているので、詳しく見たい方はどうぞ。

*普通=遷移先が変わらない

マツダコウヘイ @matskohe
© 2022
matsudakohei.com