@gabakugik (GABAKU GIK)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

データを表示させたい

解決したいこと

データを表示させたい
ログとして
(node:2263) [DEP0040] DeprecationWarning: The punycode module is deprecated. Please use a userland alternative instead.

(Use node --trace-deprecation ... to show where the warning was created)
データがありません
GET / 200 in 2491ms
コンソールログ
react-dom-client.development.js:25022 Download the React DevTools for a better development experience: https://react.dev/link/react-devtools
page.tsx:13 Server データがありません
report-hmr-latency.ts:26 [Fast Refresh] done in NaNms
これが表示されている。

例)
Supabaseからデータを取り出したい。

発生している問題・エラー

(node:2263) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
データがありません
 GET / 200 in 2491ms

コンソールログ
react-dom-client.development.js:25022 Download the React DevTools for a better development experience: https://react.dev/link/react-devtools
page.tsx:13  Server  データがありません
report-hmr-latency.ts:26 [Fast Refresh] done in NaNms

これが表示されている。

フォルダ構成
my-app/
├── app/
│   ├── components/
│   │   └── Instruments.tsx
│   ├── page.tsx
│   ├── layout.tsx
│   └── globals.css
├── utils/
│   └── supabase/
│       ├── client.ts
│       └── server.ts
├
├── public/
│   ├── favicon.ico
│   └── images/
├── .env.local
├── next.config.js
├── tsconfig.json
├── package.json
├── README.md
└── .gitignore
package.json
{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev --turbopack",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@supabase/ssr": "^0.5.1",
    "@supabase/supabase-js": "^2.45.4",
    "next": "15.3.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.3.2",
    "tailwindcss": "^4",
    "typescript": "^5"
  }
}
tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "./*"
      ]
    },
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "noEmit": true,
    "esModuleInterop": true,
    "plugins": [
      {
        "name": "next"
      }
    ]
  },
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "next-env.d.ts",
    ".next/types/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}
.env.local.

NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
/utils/supabase/servers.ts
import { createServerClient, type CookieOptions } from '@supabase/ssr';
import { cookies } from 'next/headers';

export async function createClient() {
  const cookieStore = await cookies(); // cookies() を非同期に取得

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value; // 非同期取得した cookieStore を使用
        },
        set(name: string, value: string, options: CookieOptions) {
          cookieStore.set(name, value, options);
        },
        remove(name: string, options: CookieOptions) {
          cookieStore.set(name, '', { ...options, maxAge: 0 });
        },
      },
    }
  );
}
/utils/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  );
}
/app/components/Instruments.tsx

'use client';

import { useEffect, useState } from 'react';
import { createClient } from '@/utils/supabase/client';

export default function Instruments() {
  const [instruments, setInstruments] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const supabase = createClient();

  useEffect(() => {
    async function fetchData() {
      const { data, error } = await supabase.from('instruments').select('*');
      if (error) {
        console.error('楽器データ取得エラー:', error.message, error.details);
      } else {
        console.log('初期データ:', data); // デバッグ用ログ
        setInstruments(data || []);
      }
      setLoading(false);
    }
    fetchData();

    const channel = supabase
      .channel('instruments')
      .on('postgres_changes', { event: '*', schema: 'public', table: 'instruments' }, (payload) => {
        console.log('リアルタイム更新:', payload); // デバッグ用ログ
        setInstruments((prev) => {
          if (payload.eventType === 'INSERT') return [...prev, payload.new];
          if (payload.eventType === 'UPDATE') {
            return prev.map((item) => (item.id === payload.new.id ? payload.new : item));
          }
          if (payload.eventType === 'DELETE') {
            return prev.filter((item) => item.id !== payload.old.id);
          }
          return prev;
        });
      })
      .subscribe((status) => {
        console.log('サブスクリプション状態:', status); // サブスクリプション状態をログ
      });

    return () => {
      supabase.removeChannel(channel);
    };
  }, []);

  if (loading) {
    return (
      <div className="text-center mt-10">
        <div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-gray-900 mx-auto"></div>
      </div>
    );
  }

  return (
    <div className="container mx-auto p-6">
      <h1 className="text-3xl font-bold text-gray-800 mb-6">リアルタイム楽器一覧</h1>
      <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
        {instruments.length === 0 ? (
          <div className="text-gray-500 text-center col-span-full">楽器が見つかりません</div>
        ) : (
          instruments.map((instrument) => (
            <div
              key={instrument.id}
              className="p-4 bg-blue-50 rounded-lg shadow-md hover:shadow-lg transition"
            >
              <h2 className="text-lg font-semibold text-gray-700">{instrument.name}</h2>
            </div>
          ))
        )}
      </div>
    </div>
  );
}


/app/pages.tsx
import { createClient } from '@/utils/supabase/server';

export default async function Home() {
  const supabase = await createClient();
  const { data, error } = await supabase.from('instruments').select('*');

  if (error) {
    console.error('Supabase データ取得エラー:', error.message, error.details);
    return <div className="text-red-500 text-center mt-10">エラー: {error.message}</div>;
  }

  if (!data || data.length === 0) {
    console.log('データがありません');
    return <div className="text-gray-500 text-center mt-10">楽器が見つかりません</div>;
  }

  console.log('取得データ:', data); // デバッグ用ログ

  return (
    <main className="container mx-auto p-6">
      <h1 className="text-3xl font-bold text-gray-800 mb-6">楽器カタログ</h1>
      <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
        {data.map((instrument) => (
          <div
            key={instrument.id}
            className="p-4 bg-white rounded-lg shadow-md hover:shadow-lg transition"
          >
            <h2 className="text-lg font-semibold text-gray-700">{instrument.name}</h2>
          </div>
        ))}
      </div>
    </main>
  );
}

image.png
と出る。

データは入れている
image.png

https://qiita.com/Sicut_study/items/1ab87c0c182fc42ad824
これかもしれないんですが、RLSってどこ?

自分で試したこと

色々コードを変えてみた。

Supabaseからデータがとれればいいです。
解決方法ご教授いただきたいです。
よろしくお願いいたします。
ここの部分どうなっているとかあればソース出します。

0 likes

1Answer

Your answer might help someone💌