今回は、「Next.js + Typescript」で「Recoil」と「React Hook Form」を使用した、入力画面と入力した情報を表示する確認画面の実装方法の例を紹介していきます。
検証環境
検証に使用した環境/ライブラリを次に記載します。
- React
- バージョン:18.2.0
- Next.js
- バージョン:12.1.6
- Recoil
- バージョン:0.7.4
- React Hook Form
- バージョン:7.32.2
動作例
「Recoil」と「React Hook Form」を使用した入力画面の内容を確認画面で表示する処理の動作例は、次のサイトで確認することができます。
【動作例】
【プロジェクト情報】
プログラム内容
パッケージ構成
パッケージ構成の「package.json」は、次のようになります。
{
"name": "recoil-react-hook-form",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "12.2.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "7.32.2",
"recoil": "0.7.4"
},
"devDependencies": {
"@types/node": "14.14.31",
"@types/react": "17.0.2",
"typescript": "4.1.5"
},
"license": "MIT",
"keywords": [],
"description": ""
}
ディレクトリ構成
ディレクトリ構成は、次のようになります。
.
|--pages
| |--_app.tsx
| |--confirm.tsx
| |--index.tsx
|--states
| |--atoms
| | |--inputAtom.ts
|--tyeps
| |--inputFormType.ts
「pages」には、画面表示に関連するディレクトリになります。
「states/atoms」には、状態保持に関連するディレクトリになります。
「tyeps」には、状態保持の型定義に関連するディレクトリになります。
ディレクトリ構成は、例のためプロジェクトにあわせて適宜変更してください。
状態管理
「Recoil」を使用した状態管理するための処理例は、それぞれ次のようになります。
【tyeps/inputFormType.ts】
状態保持するためのデータ型を定義します。
type InputFormTyep = {
id: string;
name: string;
};
export default InputFormTyep;
【states/atoms/inputAtom.ts】
状態保持は「atom」で管理しています。データ型で定義した情報を使用して、オブジェクトを定義します。
import { atom } from "recoil";
import InputFormType from "../../tyeps/inputFormType";
export const inputState = atom<InputFormType>({
key: "input",
default: {
id: null,
name: ""
}
});
「key」に指定する値は、ユニークとなるような値を指定する必要があります。
「default」には、初期値を設定することもできます。
詳しい使用方法については、公式サイトもあわせて確認してみてください。
画面
画面の処理例は、それぞれ次のようになります。
【pages/_app.tsx】
import type { AppProps } from "next/app";
import { RecoilRoot } from "recoil";
function App({ Component, pageProps }: AppProps) {
return (
<RecoilRoot>
<div>Next.js + TypeScript</div>
<Component {...pageProps} />
</RecoilRoot>
);
}
export default App;
状態管理をするためには「RecoilRoot」で括る必要があります。詳しい使用方法については、公式サイトもあわせて確認してみてください。
【pages/index.tsx】
入力画面の作成します。
import type { NextPage } from "next";
import { useForm } from "react-hook-form";
import { useRecoilState } from "recoil";
import { inputState } from "../states/atoms/inputAtom";
import InputFormType from "../tyeps/inputFormType";
import Router from "next/router";
const Input: NextPage = () => {
const [input, setInput] = useRecoilState(inputState);
const { register, handleSubmit } = useForm<InputFormType>({
defaultValues: {
id: input.id,
name: input.name
}
});
const onSubmit = handleSubmit((data: InputFormType) => {
setInput((currentInput) => ({
...currentInput,
...{
id: data.id,
name: data.name
}
}));
Router.push("/confirm");
});
return (
<div>
<form onSubmit={onSubmit}>
<div>
<label>
<span>id:</span>
<input type="text" {...register("id")} />
</label>
</div>
<div>
<label>
<span>name:</span>
<input type="text" {...register("name")} />
</label>
</div>
<div>
<button type="submit">confirm</button>
</div>
</form>
</div>
);
};
export default Input;
「useRecoilState」に作成した「atom」を指定して使用します。
const [input, setInput] = useRecoilState(inputState);
処理例の指定方法の場合は、読み取り/書き込みの両方ができるようになります。詳しい使用方法については、公式サイトもあわせて確認してみてください。
「useForm」を使用してフォーム情報のオブジェクトを定義します。
const { register, handleSubmit } = useForm<InputFormType>({
defaultValues: {
id: input.id,
name: input.name
}
});
「defaultValues」には、「Recoil」から取得した情報を使用して初期値を設定しています。指定することで「確認画面」から戻ってきたときも値を保持しておくことが可能となります。
フォームのSubmitを実行するときの処理になります。入力した情報を「Recoil」に設定する処理を実施しています。
const onSubmit = handleSubmit((data: InputFormType) => {
setInput((currentInput) => ({
...currentInput,
...{
id: data.id,
name: data.name
}
}));
Router.push("/confirm");
});
値を設定後は、「確認画面」へ遷移する動作を実施しています。
【pages/confirm.tsx】
確認画面を作成します。
import type { NextPage } from "next";
import Link from "next/link";
import { useRecoilValue } from "recoil";
import { inputState } from "../states/atoms/inputAtom";
const Confirm: NextPage = () => {
const input = useRecoilValue(inputState);
return (
<div>
<form>
<div>
<label>
<span>id:</span>
<div>{input.id}</div>
</label>
</div>
<div>
<label>
<span>name:</span>
<div>{input.name}</div>
</label>
</div>
<div>
<Link href="/">Back Input</Link>
</div>
</form>
</div>
);
};
export default Confirm;
「useRecoilValue」に作成した「atom」を指定します。
const input = useRecoilValue(inputState);
処理例の指定方法の場合は、読み取りのみができるようになります。詳しい使用方法については、公式サイトもあわせて確認してみてください。
まとめ
「Recoil」と「React Hook Form」を使用した実装方法の例を紹介しました。