◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-04-18中級

Rork アプリで Supabase のデータが取得できない・表示されないときの原因別対処法

Rork × Supabase でデータが表示されない原因を体系的に診断する方法を解説。RLS設定ミス・APIキーの誤り・非同期処理の落とし穴など、実際によく起きるパターンをコード例付きで紹介します。

Supabase37トラブルシューティング85RLS3データ取得デバッグ22

Rork で Supabase を使ったアプリを作ったのに、データが一向に表示されありません。そのパターン、私も何度か経験しました。

厄介なのは、エラーメッセージが出ないこともあることです。画面は正常に表示されているのに、リストが空のまま。コンソールを見ても undefined が返ってきているだけ。「Supabase の設定は合ってるはずなのに…」と途方に暮れる感覚は、初心者にとってかなり心が折れます。

ここではよくある原因を4つのパターンに絞り込んで、それぞれの診断方法と対処法を整理しています。順番に確認していただくと、多くのケースで原因を特定できると思います。

パターン1: RLS(Row Level Security)が原因 — 最も多い落とし穴

Supabase でデータが取得できないとき、原因の半分以上は RLS(行レベルセキュリティ)の設定にあります。

RLS を有効にすると、デフォルトではすべてのアクセスが拒否されます。「テーブルにデータは入っているはずなのに取れない」という状況のほとんどが、これが原因です。

診断方法

Supabase ダッシュボードの「Table Editor」を開き、テーブルを直接クリックしてみてください。データが表示される場合、アプリ側の認証状態と RLS ポリシーのズレが原因です。

次に「Authentication → Policies」でテーブルのポリシーを確認します。

-- こういう状態のとき、データが取れません
-- ポリシー: なし(有効: RLS ON)
-- すべてのユーザーからのアクセスが拒否されます
 
-- 開発中の一時的な確認用(本番では使わない)
create policy "Allow all for testing"
  on your_table
  for select
  using (true);

ログイン済みユーザーにだけデータを返す正しいポリシー

-- ユーザー自身のデータだけを読めるようにする(一般的なパターン)
create policy "Users can read their own data"
  on your_table
  for select
  using (auth.uid() = user_id);

ポイントは auth.uid() です。これは Supabase が提供する関数で、現在ログイン中のユーザーの ID を返します。テーブルの user_id カラムと一致するレコードだけが返ってきます。

ログイン前にデータを取得しようとしていませんか?

アプリ起動直後、まだログインが完了していない状態でデータを取得しようとすると、RLS によってすべて弾かれます。認証状態の確認を必ず先に行いましょう。

// ❌ 問題のあるパターン(認証確認なしでデータ取得)
useEffect(() => {
  fetchData(); // ログイン前に実行される可能性がある
}, []);
 
// ✅ 認証後にだけ取得するパターン
useEffect(() => {
  const { data: { subscription } } = supabase.auth.onAuthStateChange(
    (event, session) => {
      if (session) {
        fetchData(); // ログイン済みのときだけ実行
      }
    }
  );
  return () => subscription.unsubscribe();
}, []);

パターン2: Supabase の URL・API キーの設定ミス

意外と多いのが、.env ファイルの設定ミスです。特に複数のプロジェクトを同時に進めているときに起きやすいです。

確認すべきこと

// supabase.ts(または supabase/client.ts)
import { createClient } from '@supabase/supabase-js';
 
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL\!;
const supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY\!;
 
// 開発中はこのログで確認できます
console.log('Supabase URL:', supabaseUrl?.substring(0, 30) + '...');
 
export const supabase = createClient(supabaseUrl, supabaseAnonKey);

Expo(React Native)の場合、環境変数は EXPO_PUBLIC_ で始まる必要があります。この接頭辞がないと、クライアント側のコードから変数にアクセスできません。

Supabase ダッシュボードの「Settings → API」で確認できる値と、アプリが使っている値が一致しているか確認してください。特に「anon key」と「service_role key」を間違えないよう注意が必要です(service_role key はサーバーサイドでのみ使うものです)。

Rork での環境変数設定については、Rork の環境変数・設定ミスのトラブルシューティングも参考にしてみてください。

パターン3: 非同期処理の実装ミスでデータが空になる

RLS も API キーも問題なさそうなのにデータが表示されない場合、JavaScript の非同期処理の扱いに問題があるケースです。

よくある間違いパターン

// ❌ async/await が正しく使えていない例
const fetchData = () => {
  const { data, error } = supabase
    .from('posts')
    .select('*');
  // Promiseをawaitしていないため、dataはundefinedのまま
  setData(data); 
};
 
// ✅ 正しい非同期処理
const fetchData = async () => {
  const { data, error } = await supabase
    .from('posts')
    .select('*');
  
  if (error) {
    console.error('取得エラー:', error.message);
    return;
  }
  
  setData(data ?? []); // nullの場合は空配列にする
};

await を忘れるのは本当によくある間違いです。Promise は即座に値を返さないので、await なしで data を参照すると undefined になります。

React のレンダリングタイミングの問題

// ❌ コンポーネントがマウントされる前に状態が設定される可能性
const MyComponent = () => {
  const [posts, setPosts] = useState(null); // ← null で初期化
  
  fetchData(); // useEffect外で呼び出している
  
  return <View>{posts.map(...)}</View>; // nullのときにクラッシュ
};
 
// ✅ 正しいパターン
const MyComponent = () => {
  const [posts, setPosts] = useState<Post[]>([]); // 空配列で初期化
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    const fetch = async () => {
      setLoading(true);
      const { data, error } = await supabase.from('posts').select('*');
      if (\!error && data) setPosts(data);
      setLoading(false);
    };
    fetch();
  }, []);
  
  if (loading) return <ActivityIndicator />;
  if (posts.length === 0) return <Text>データがありません</Text>;
  
  return <FlatList data={posts} renderItem={...} />;
};

初期値を null にすると .map() を呼び出したときにクラッシュします。配列を扱う場合は必ず空配列 [] で初期化するのが安全です。

パターン4: テーブル名・カラム名の間違い

地味ですが、これも頻繁に起きます。Supabase のテーブル名はデフォルトでスネークケース(user_profiles)ですが、コード側でキャメルケース(userProfiles)を使ってしまうケースです。

// ❌ テーブル名・カラム名が違う
const { data } = await supabase
  .from('userProfiles') // ← Supabase側はuser_profilesかもしれない
  .select('userName'); // ← Supabase側はuser_nameかもしれない
 
// ✅ ダッシュボードで確認した正確な名前を使う
const { data } = await supabase
  .from('user_profiles') // ← ダッシュボードで確認
  .select('user_name, avatar_url, created_at');

Supabase ダッシュボードの「Table Editor」でテーブル名とカラム名を正確に確認してから書くようにしましょう。

また、select('*') で全カラム取得してから、返ってくるデータの形を console.log で確認するのが一番手っ取り早いです。

診断フロー — 迷ったらこの順番で確認

まとめると、データが取得できないときは次の順番で確認するのが効率的です。

まずは console.log(error) を追加して、エラーメッセージを確認してください。エラーが null で data も null の場合は、RLS が原因である可能性が高いです。エラーに「Invalid API key」が含まれる場合は API キーの問題です。

次に Supabase ダッシュボードの「Logs → API Logs」を確認します。リアルタイムでどんなクエリが飛んでいるか、ステータスコードが何かを確認できます。406 が返っている場合は RLS によるアクセス拒否が疑われます。

データベース接続エラーの詳細なトラブルシューティングや、Supabase の認証エラーを解決する方法も合わせて参考にしてみてください。

次のステップ

データが取得できるようになったら、次は実際にアプリとして動くかを実機でテストしてみましょう。シミュレーターでは再現しない問題が実機で出ることもあります。

Supabase の RLS は最初は難しく感じるかもしれませんが、一度仕組みを理解すると、細かいアクセス制御ができる強力な機能として活用できます。まずは開発中は一時的にすべてのアクセスを許可するポリシーを設定して動作確認し、リリース前に適切なポリシーに絞っていくアプローチがおすすめです。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⬡ 開発ツール2026-10-15
EXPO_PUBLIC_ の値が、開発では読めて本番だけ undefined になる書き方を、変換結果で見分けます
API の URL が開発中は読めるのに、ビルドした途端に undefined になる。原因は process.env の書き方でした。babel-preset-expo の変換結果を開発・本番で並べ、置き換わる書き方と残ってしまう書き方を表にしました。
⬡ 開発ツール2026-10-07
日本語の見出しだけ太字にならない — Android で fontWeight が効かないときの切り分けと直し方
Rork で作ったアプリで、iPhone では太字なのに Android では日本語の見出しが細いままになる症状の切り分け記事です。原因の見分け方、fontFamily を重みごとに分ける直し方、確認用コードを載せています。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。