はじめに
Supabase.jsでフォームに入力された値をSupabaseのレコードに追加&削除する方法を紹介します。
前提条件
本記事では以下の環境で動作検証を行なっています。
- Vite 8.3.0
- React 19.2.8
- @supabase/supabase-js 2.117.1
React+Vite環境でSupabaseのクライアント設定をする方法については以下の記事で解説していますので、まだ設定が出来ていない方は参考にしてみてください。
また、本記事ではSupabaseに以下のテーブルが作成されている事を前提としています。
まだテーブルの作成が出来ていない方は以下画像を参考にテーブルの作成を行なってください。
idとcreated_atはデフォルト値を設定し、contentsとtimeに値を追加する想定となっています。
入力フォーム
入力フォームのコードです。このコードに追記していく形でSupabaseのレコードにデータの追加と削除を行うコードを書いていきます。
import { useEffect, useState } from "react";
import { supabase } from "./lib/supabaseClient";
const App = () => {
const [records, setRecords] = useState([]);
const [time, setTime] = useState(0);
const [contents, setContents] = useState("");
useEffect(() => {
getRecords();
}, []);
// Supabaseに登録されているレコードを取得する
const getRecords = async () => {
const { data, error } = await supabase.from("test-record").select();
if (error) {
console.error(error);
return;
}
setRecords(data);
};
const onChangeTime = (e) => {
const value = e.target.value;
setTime(Number(value));
};
const onChangeContents = (e) => {
const value = e.target.value;
setContents(value);
};
return (
<>
<div>
時間:
<input type="number" min="0" onChange={onChangeTime} value={time} />
</div>
<div>
内容:
<input type="text" onChange={onChangeContents} value={contents} />
</div>
<button>送信</button>
<ul>
{records.map((record) => (
<li key={record.id}>
<div>時間:{record.time}h</div>
<div>内容:{record.contents}</div>
<button>削除</button>
</li>
))}
</ul>
</>
);
};
export default App;
ちなみに見た目はこんな感じです。CSSを当てずブラウザのデフォルトスタイルとしています。
レコードを追加する
フォームに入力した値をSupabeseのレコードに追加します。
import { useEffect, useState } from "react";
import { supabase } from "./lib/supabaseClient";
const App = () => {
const [records, setRecords] = useState([]);
const [time, setTime] = useState(0);
const [contents, setContents] = useState("");
useEffect(() => {
getRecords();
}, []);
// Supabaseに登録されているレコードを取得する
const getRecords = async () => {
const { data, error } = await supabase.from("test-record").select();
if (error) {
console.error(error);
return;
}
setRecords(data);
};
const onChangeTime = (e) => {
const value = e.target.value;
setTime(Number(value));
};
const onChangeContents = (e) => {
const value = e.target.value;
setContents(value);
};
// 追加:Supabaseのレコードに追加する処理
const onClickData = async () => {
const { error } = await supabase
.from("test-record")
.insert({ time, contents });
if (error) {
console.error(error);
return;
}
await getRecords();
};
return (
<>
<div>
時間:
<input type="number" min="0" onChange={onChangeTime} value={time} />
</div>
<div>
内容:
<input type="text" onChange={onChangeContents} value={contents} />
</div>
{/* クリックイベント追加 */}
<button onClick={onClickData}>送信</button>
<ul>
{records.map((record) => (
<li key={record.id}>
<div>時間:{record.time}h</div>
<div>内容:{record.contents}</div>
<button>削除</button>
</li>
))}
</ul>
</>
);
};
export default App;
レコードの追加にはSupabase.jsのinsertメソッドを使用します。
引数はオブジェクトですが、プロパティのキーはSupabaseに追加しているテーブルのnameにする必要があります。
例えばSupabaseに上画像のテーブルを作成していて、この中のcontentsとtimeにデータを追加したい場合は次のように書きます。
const onClickData = async () => {
const { error } = await supabase
.from("test-record")
.insert({ time, contents });
if (error) {
console.error(error);
return;
}
await getRecords();
};
insertメソッドの引数のオブジェクトは省略記法で書いていますが次のように書いても問題ないです。
const onClickData = async () => {
const { error } = await supabase
.from("test-record")
.insert({ time:time, contents:contents });
if (error) {
console.error(error);
return;
}
await getRecords();
};
レコードを削除する
続いてレコードの削除です。
import { useEffect, useState } from "react";
import { supabase } from "./lib/supabaseClient";
const App = () => {
const [records, setRecords] = useState([]);
const [time, setTime] = useState(0);
const [contents, setContents] = useState("");
useEffect(() => {
getRecords();
}, []);
// Supabaseに登録されているレコードを取得する
const getRecords = async () => {
const { data, error } = await supabase.from("test-record").select();
if (error) {
console.error(error);
return;
}
setRecords(data);
};
const onChangeTime = (e) => {
const value = e.target.value;
setTime(Number(value));
};
const onChangeContents = (e) => {
const value = e.target.value;
setContents(value);
};
// Supabaseのレコードに追加する処理
const onClickData = async () => {
const { error } = await supabase
.from("test-record")
.insert({ time: time, contents: contents });
if (error) {
console.error(error);
return;
}
await getRecords();
};
// 追加:Supabaseのレコードを削除する処理
const onClickDelete = async (id) => {
const { error } = await supabase
.from("test-record").delete().match({ id });
if (error) {
console.error(error);
return;
}
await getRecords();
};
return (
<>
<div>
時間:
<input type="number" min="0" onChange={onChangeTime} value={time} />
</div>
<div>
内容:
<input type="text" onChange={onChangeContents} value={contents} />
</div>
<button onClick={onClickData}>送信</button>
<ul>
{records.map((record) => (
<li key={record.id}>
<div>時間:{record.time}h</div>
<div>内容:{record.contents}</div>
{/* クリックイベント追加 */}
<button onClick={() => onClickDelete(record.id)}>削除</button>
</li>
))}
</ul>
</>
);
};
export default App;
Supabaseのレコードの削除にはdeleteメソッドとmatchメソッドを使用します。
deleteメソッドは削除したいレコードを指定するフィルターとなるメソッドと組み合わせて使用します。
メソッドチェーンで繋いだmatchメソッドの引数はオブジェクトになります。キー名は削除したいレコードのid名を指定しましょう。
おわりに
今回は最低限の入力フォームの機能としましたが、よく使うのでぜひ覚えてしまいましょう。


