はじめに
supabaseで、リレーションしているテーブルにIDを紐づける時、
少し手法に迷ったので記事にします
テーブルの状況
現在のテーブル状況はこちら
userテーブル
カラム名 | 型 |
---|---|
id | string |
string | |
name | string |
created_at | string |
user_id | string |
reviews_id | string |
record_id | string |
goals_id | string |
goalsテーブル
カラム名 | 型 |
---|---|
id | string |
target_records | string |
current_records | string |
target_sales_hours | string |
current_sales_hours | string |
week_start_date | string |
idとgoals_idを紐づけています
問題
SQLを使う?とか考えていたりして、とにかくやり方に迷いました。
一旦、作業をバラバラにして考えてみたところ、大雑把に三つのやり方に分けられるのかなと。
1.goalsテーブルに挿入する
2.goalsテーブルのidを取得する
3.それを現在ログインしているuserのテーブルに挿入する
こんな感じで考えました。(もっといい手法があったらすみません)
解決方法
まずは2つのapiを作成します
// insertをしてデータを挿入
export const InsertGoal = async (goal: GoalTargetData) => {
const { data, error } = await supabase.from("goals").insert(goal).select("id").single();
if (error) {
throw error;
}
return data.id;
};
//user_idに挿入するためのAPI
export const UpdateUserGoalId = async (userId: string, goalId: string) => {
const { error } = await supabase.from("users").update({ goals_id: goalId }).eq("id", userId);
if (error) {
throw error;
}
};
onClickとかでデータを送るときのコードを準備
const [user] = useAtom(userAtom);
const [learning, setLearning] = useState<number>(0);
const [sales, setSales] = useState<number>(0);
const [works, setWorks] = useState<number>(0);
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
setIsLoading(true);
// NOTE: データの整形をここで行う
const goal = {
target_records_hours: learning,
target_sales_hours: sales,
target_works_hours: works,
};
const goalId = await InsertGoal(goal);
if (user?.id) {
await UpdateUserGoalId(user.id, goalId);
}
} catch (error) {
if (error instanceof Error) {
console.log(error);
setError(error.message);
} else {
setError("エラーが発生しました");
}
} finally {
setIsLoading(false);
}
};
今回は状況切り分けのために、try
を使ってconsole
上でエラーハンドリングをしましたが、ここはちゃんとしたコードを書いた方がいいと思います
まず、さっきのやり方で考えると、
const goalId = await InsertGoal(goal);
if (user?.id) {
await UpdateUserGoalId(user.id, goalId);
}
InsertGoal
はreturn
でdata.id
を返しているので、
それを一旦、変数で格納します
その後、UpdateUserGoalId()
を使用します
api側で決めた引数としては、
第一引数が、userIdで、第二引数が、goalIdです
そして、今回はjotaiで管理していたuser
つまり、今回ログインしているユーザーの情報を、atomで引っ張ってきます
const [user] = useAtom(userAtom);
そこでuser.id
を設定してあげると、今ログインしているユーザーのIDにあるカラムのgoals_id
に入るってわけですね。
おわりに
手法に迷うことはありますが、迷ったり詰まったら一度作業をバラバラにして考えてみる。これを徹底していこうと思います。