はじめに
Supabaseの戻り値の指定を間違えてエラーが起きてしまい、解決に時間がかかってしまったので記事にします。
問題
console.logにはsupabaseに登録しているデータを取得しているのが確認できるが、画面ではコンポーネントのエラーが発生している。
App.js
useEffect(() => {
const getRecords = async () => {
try {
setIsLoading(true);
const allRecords = await getAllRecords();
console.log("supabase", allRecords);
setRecords(allRecords);
const initialTotalTime = allRecords.reduce(
(accumulator, currentValue) => accumulator + currentValue.time,
0
);
setTotalTime(initialTotalTime);
} catch (error) {
console.log("エラー", error);
setError("エラー発生");
} finally {
setIsLoading(false);
}
};
getRecords();
}, []);
supabaseFunction.js
import { supabase } from "./supabase";
export const getAllRecords = async () => {
const records = await supabase.from("study-record").select("*");
return records;
};
実際のエラーメッセージ:
TypeError: allRecords.reduce is not a function
解決方法
supabaseFunction.jsのreturn recordのところにdataプロパティを明示的に指定する必要があった。
supabaseFunction.js
import { supabase } from "./supabase";
export const getAllRecords = async () => {
const records = await supabase.from("study-record").select("*");
return records.data;
};
Supabaseのレスポンスでは以下の構造のオブジェクトを返します。
{
data: [...], // 実際のデータ配列
error: null, // エラーがあればエラーオブジェクト、なければnull
count: null, // カウントクエリの結果
status: 200, // HTTPステータスコード
statusText: "" // HTTPステータステキスト
}
return records; にすると、オブジェクト全体を返しているのに、React側でそれを配列として扱おうとしてエラーが起きていた。具体的には、allRecords.reduceを実行しようとしたが、allRecordsはオブジェクトであり、reduceメソッドを持っていないためエラーになった。
おわりに
戻り値が配列なのか、オブジェクトなのか、オブジェクトならどのキーの情報が欲しいのか考える癖をつけるようにする。また、APIからのレスポンスデータは、console.logでその構造を確認してから処理を進めていきたい。
参考