問題
チェックボックスを複数チェックし、supabaseに保存したい。
シンプルですが実装は意外と難しかったです。
解決方法
ソースコードとコメントは以下になります。
import { useEffect, useState } from 'react';
// supabaseの設定ファイルの説明は割愛
import { supabase } from './lib/supabaseClient';
function WordsPage() {
type Word = {
word_id: number;
word_name: string;
mastered: boolean;
}
const [words, setWords] = useState<Word[]>([]);
useEffect(() => {
const fetchWords = async () => {
const { data, error } = await supabase.from('word').select('*')
.order('updated_at', { ascending: false, nullsFirst: false })
.order('created_at', { ascending: false });
if (error) {
console.error('Error fetching words:', error.message);
} else {
setWords(data);
}
}
fetchWords();
}, []);
// idを指定する
const handleCheckboxChange = async (id: number) => {
// 該当wordのチェックボックスの状態を反転させる
// updatedWordsは、masteredフラグが反転された新しいwords配列
const updatedWords = words.map((word) =>
// 三項演算子 trueの場合はmasteredフラグを反転し、falseの場合はwordをそのまま返す
word.word_id === id ? { ...word, mastered: !word.mastered } : word
);
setWords(updatedWords);
const { error } = await supabase
.from('word')
// 新しい配列 updatedWordsから、word_id が id のオブジェクトを探し、そのオブジェクトの mastered 値を取得
// ?. は オプショナルチェイニング:見つからなければ undefined を返す
.update({ mastered: updatedWords.find(word => word.word_id === id)?.mastered })
// eq は "equal"(等しい) の略で、Supabase(SQLクエリビルダー)で WHERE 条件 を指定する
.eq('word_id', id)
.order('updated_at', { ascending: false, nullsFirst: false })
.order('created_at', { ascending: false });
if (error) {
console.error('Error updating word:', error.message);
}
}
return (
<>
<h1>Word List</h1>
{words.map((item) => (
<div key={item.word_id}>
<div>{item.word_name}</div>
// チェックボックスの箇所
<label>mastered</label>
<input
type="checkbox"
checked={item.mastered}
onChange={() => handleCheckboxChange(item.word_id)}
/>
</div>
))}
</>
)
};
export default WordsPage;
実際の画面
チェックボックスにチェックを入れて更新しても、その状態が保存されてチェックが反映されている。
終わりに
チェックボックスの状態を複数管理してデータベースと同期させるのは、一見シンプルですが、
状態管理や非同期処理の扱いが絡むため意外に難しいです。
私が実際にやってみて大事だと感じたのは以下の3点です。
-
やりたいことを明確にする
→ どの単語のチェック状態をどう変えたいのか、仕様をはっきりさせる -
ChatGPTに何度も相談する
→ 自分でつまずいたポイントや疑問を細かく質問することで理解が深まる -
何をやっているかを理解する
→ コードの中で、状態をどう更新し、データベースにどう反映しているかを理解することが肝心
この3つを意識しながら進めると、複雑な機能も着実に実装できるようになります。