論文情報テキストを作成するツールをNext.jsで実装

更新:2025-01-09
JavaScript

概要

著者名や論文誌名などを入力して、決められたフォーマットの論文情報テキストを作成するツールを、Next.jsで実装する。

フォーマット

著者名, 著者名, 著者名 (年) 論文タイトル. 論文誌名, 巻(号), 開始ページ-終了ページ

サンプル

著者情報は、実在しなさそうな名前を生成AIに考えてもらった。論文情報は、厨二発想で適当に。

星詠月歌, 蒼空海斗, 紅叶霧華 (2025) 超次元転移装置に螺旋構造を用いた場合に起こりうる二極化現象について. 超次元転移研究集, 1(2), 3-4

英語の場合は、著者名を「名字 名前のイニシャル」とする。

Hoshiyomi T, Aozora K, Koyo K (2025) 超次元転移装置に螺旋構造を用いた場合に起こりうる二極化現象について. 超次元転移研究集, 1(2), 3-4

アクセプト状態(詳しくは知らない)の場合は、末尾にその旨を記載する。

星詠月歌, 蒼空海斗, 紅叶霧華 (2025) 超次元転移装置に螺旋構造を用いた場合に起こりうる二極化現象について. 超次元転移研究集, 1(2), 3-4 (accepted)

成果物

Vercelにデプロイした。
https://paper-info-text.vercel.app/

特に認証情報など含まないので、リポジトリはPublicで。
https://github.com/namakurajin/paper-info-text

プロジェクトの作成

プロジェクトディレクトリを用意し、中に展開。

/project-dir
npx create-next-app@latest .

Tailwindは使わない。それ以外はデフォルトで。

/project-dir
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like your code inside a `src/` directory? No / Yes
Would you like to use App Router? (recommended) … No / Yes
Would you like to use Turbopack for `next dev`? … No / Yes
Would you like to customize the import alias (`@/*` by default)? … No / Yes

開発サーバが起動できれば完了。

/project-dir
npm run dev
# http://localhost:3000/

開発環境の整備

モジュールの追加

/project-dir
npm i @ark-ui/react destyle.css lucide-react react-toastify
モジュール名簡易説明
@ark-ui/reactヘッドレスUIライブラリ。
lucide-reactアイコンライブラリ。
react-toastifyトーストUIライブラリ。
/project-dir
npm i -D sass
モジュール名簡易説明
sassSassによるスタイリング。

雑記

Reactおさらい

useStateのエラー

You’re importing a component that needs useState. This React hook only works in a client component. To fix, mark the file (or its parent) with the "use client" directive.

useStateを使うコンポーネントを使用する場合は、"use client";が必要。

ループのエラー

Each child in a list should have a unique “key” prop.

map()でループさせる要素には、key属性が必要。

Next.jsおさらい

Hydrationのエラー

Hydration failed because the server rendered HTML didn’t match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used

Chromeの拡張機能「ColorZilla」が原因でエラーが出たので、無効にした。

faviconやOGP

決められた名前で配置すれば自動で設定してくれる。
https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image
https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons

UIライブラリ

ヘッドレスUI(=スタイルなしコンポーネント)のArk UIを使用してみた。以下はチェックボックスの実装例で、ほとんどArk UIのCheckboxに関するドキュメントそのまま。

/project-dir/src/components/InputCheckbox.tsx
import { useState } from 'react';
import { Checkbox } from '@ark-ui/react/checkbox';
import { CheckIcon } from 'lucide-react'
import styles from './InputCheckbox.module.scss';
interface Props {
label: string;
name: string;
onChangeStatus(name: string, isChecked: boolean): void;
};
export default function InputCheckbox({label, name, onChangeStatus}: Props) {
const [checked, setChecked] = useState<Checkbox.CheckedState>(false);
const handleChange = (checked: Checkbox.CheckedState) => {
if (checked === 'indeterminate') return; // 今回は不確定要素を考慮しない
setChecked(checked);
onChangeStatus(name, checked);
};
return (
<Checkbox.Root
className={styles.wrapper}
checked={checked}
onCheckedChange={(e) => handleChange(e.checked)}
>
<Checkbox.Control className={styles.checkbox}>
<Checkbox.Indicator>
<CheckIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.HiddenInput name={name} className={styles.input} />
<Checkbox.Label>{label}</Checkbox.Label>
</Checkbox.Root>
);
}

トースト

以下の記事を参考にした。
https://zenn.dev/koyabluetech/articles/78f6a4caf096e2

続く...かもね