[Flutter]Hono✖️Supabaseでアプリを作る- delete -
ぽちぽちのつどいGW Advent(?) Calendar2日目の記事です!
今日は少し前から書いてるHonoとSupabaseをつかった開発の備忘録の最後deleteです。
HonoとSupabaseでアプリを作った話
触れる話
CRUD操作とFlutterの実装
触れない話
デプロイの仕方
Honoの基本
Honoの基本とGet/postについてはこちら
Honoの実装
get編やpost編をみていただいたかたならわかるかと思いますがこれもまたシンプルに記述できます。
今回も私はGet/post同様にSupabaseにデータを追加する専用の関数を作成して成功したかどうかをjson型で返すようにしました。
Honoではdelete型はapp.deleteで実装します。非常にシンプルですね。
今回は名前を削除する関数を作成します。
今回はusersテーブルの該当するnameを探して削除します。
今回はpost同様関数の中でテーブルなどを指定して書いてますがget編同様に変数化しても同じことができると思います。
export async function deleteUser(
SUPABASE_URL: string,
SUPABASE_API_KEY: string,
name: String
) {
const supabase = createClient(SUPABASE_URL, SUPABASE_API_KEY);
try {
const { data, error } = await supabase
.from('users')
.delete()
.eq('username', name);
if (error) {
console.error('Supabase error:', error);
throw error;
}
return '成功しました';
} catch (error) {
console.error('Error fetching user names:', error);
return [];
}
}
流れとしては、fromでテーブル指定 → deleteで削除指示 → eqで条件指定するだけ。
改めて見ると、Supabase用のTypeScriptライブラリがとても直感的に作られていることがわかりますねありがたい🙏
次はHonoの実装です。
SupabasenのURLなどの環境変数の管理もHonoは簡単に実行できてHonoは.dev.vars
でdotenvなどを仲介せずにc.で環境変数にアクセスできます。
app.delete
でdelete型のHTTP通信が行えるようになるので次のように記述します。
app.delete('/deleteUser', async (c) => {
const SUPABASE_URL = (c.env as { SUPABASE_URL: string }).SUPABASE_URL;
const SUPABASE_API_KEY = (c.env as { SUPABASE_API_KEY: string })
.SUPABASE_API_KEY;
const { name } = await c.req.json();
const result = await deleteUser(SUPABASE_URL, SUPABASE_API_KEY, name);
return c.json({ result: result });
});
最初にURLとAPI_KEYを環境変数から取得して必要な情報を受け取って最初に作った関数に渡して戻り値を変数に定義してjsonで返すと完成です。
Flutter
Flutterでは作成したAPIに名前を渡して削除する処理を記述します。
実際にはdioやRiverpodを使用するかと思いますが今回の趣旨と外れるのでget/post同様今回もフロントから直接通信させます。
String res = "";
void deleteData(name) async {
final response = await http.post(
Uri.parse("${api}/deleteUser"),
headers: {'Content-Type': 'application/json'},
body: json.encode({'name': name}),
);
if (response.statusCode == 200) {
setState(() {
res = json.decode(response.body)['result'];
});
} else {
setState(() {
res = 'Failed to load data';
});
}
}
deleteData関数に引数として今回はname
を渡してjsonで通信してさっき作った削除リクエストをAPI側で行ってその結果がresultとしてdecodeすることで見ることができるというものです。
あとはfetchData(Honoの処理は過去記事を参考にしてください)などの関数と組み合わせて以下のようなListViewを作成して端にdeleteアイコンをつけてあげると削除できるようになると思います。
String msg = "";
List<dynamic> names = [];
void fetchData() async {
final response = await http.get(Uri.parse(api));
final responseDB = await http.get(Uri.parse('${api}db/read'));
if (response.statusCode == 200) {
setState(() {
names = json.decode(utf8.decode(responseDB.bodyBytes))['users'];
});
} else {
setState(() {
msg = 'Failed to load data';
});
}
}
ListView.builder(
itemCount: names.length,
itemBuilder: (context, index) {
return Column(
children: [
ListTile(
leading: const Icon(Icons.person),
title: Text(names[index]),
/// 今回部分
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
deleteData(names[index]);
fetchData();
},
),
),
const Divider(height: 0),
],
);
},
)
あとは帰ってきたjsonデータに含まれる成功かどうかというデータをsnackbarなどでフロントに表示してやれば完成です。
まとめ
Honoは意外と簡単に実装できることがわかったかと思います。delete型は以上です。
FluterというよりはSupabaseとHonoという実装の話をメインにしました。FlutterでのAPI実装については丁寧な記事が他の方が書かれていると思うのでそちらを参照してください(笑)。
これらを踏まえてFlutterの実装ではテスト実装を想定しています。本番環境ではriverpod等を使用することが多いと思いますのでそちらの実装に合わせてみると良いと思います。
JSONのencode/decode
はfreezedなどで型安全にする あたりを意識するとさらにレベルアップできるはずです。
一応これで一通りupdate以外は終わったかなと思いますupdateはまたいつかのAdvent(?) Calendarで書こうと思います!
Discussion
SupabaseSDK書きやすくていいよね