使用 useSWR returns 未定义从 Firebase 获取的数据

Data fetched from Firebase using useSWR returns undefined

我正在学习一门课程,其中我使用 useSWR 从 Firebase 获取数据并使用它来设置状态。但是,当我尝试控制台记录数据时,我得到未定义并且屏幕显示正在加载。这有什么理由吗。我什至复制了讲师使用的完全相同的代码(API link 除外)。

import { useEffect, useState } from 'react';
import useSWR from 'swr';

function LastSalesPage() {
  const [sales, setSales] = useState();
  // const [isLoading, setIsLoading] = useState(false);

  const { data, error } = useSWR(
    'https://nextjs-2021-default-rtdb.firebaseio.com/sales.json'
  );

  console.log('Data:', data);

  useEffect(() => {
    if (data) {
      const transformedSales = [];

      for (const key in data) {
        transformedSales.push({
          id: key,
          username: data[key].username,
          volume: data[key].volume,
        });
      }

      setSales(transformedSales);
    }
  }, [data]);

  if (error) {
    return <p>Failed to load.</p>;
  }

  if (!data || !sales) {
    return <p>Loading...</p>;
  }

  return (
    <ul>
      {sales.map((sale) => (
        <li key={sale.id}>
          {sale.username} - ${sale.volume}
        </li>
      ))}
    </ul>
  );
}

export default LastSalesPage;

根据官方文档-

the useSWR hook accepts a key string and a fetcher function. key is a unique identifier of the data (normally the API URL) and will be passed to fetcher. fetcher can be any asynchronous function which returns the data, you can use the native fetch or tools like Axios.

看来你根本就没有在那里传递任何提取器。

尝试像这样定义钩子:

const fetcher = (url) => fetch(url).then((res) => res.json());

  const { data, error } = useSWR(
    'https://nextjs-2021-default-rtdb.firebaseio.com/sales.json',
    fetcher
  );
  const { data : userData, error: errorUserData } = useSWR(
    'https://nextjs-2021-default-rtdb.firebaseio.com/sales.json'
  );

还有你的完整文件(工作,由我测试):

import { useEffect, useState } from 'react';
import useSWR from 'swr';

function LastSalesPage() {
  const [sales, setSales] = useState();
  // const [isLoading, setIsLoading] = useState(false);

  const { data: userData, error: userDataError } = useSWR(
    'https://nextjs-2021-default-rtdb.firebaseio.com/sales.json'
  );



  if (userDataError) {
    return <p>Failed to load.</p>;
  }

  if (!userData) {
    return <p>Loading...</p>;
  }
  if (userData){
  let transformedSales = [];

      for (const key in userData) {
        transformedSales.push({
          id: key,
          username: userData[key].username,
          volume: userData[key].volume,
        });
  }
  console.log(userData, transformedSales)
  let sales = transformedSales
  return (
    <ul>
      {sales.map((sale) => (
        <li key={sale.id}>
          {sale.username} - ${sale.volume}
        </li>
      ))}
    </ul>
  );
  }
}

export default LastSalesPage;

P.S 不要使用 useEffect() 钩子(反应钩子)来获取数据,useSWR 非常适合这个目的。

P.S (2) 你不需要 fetcher 来获取没有特殊参数的数据,所以只需 = useSWR('/api/path')

关于fetcher的说明:如果你勾选official docs, fetcher is optional param. "The fetcher here is an async function that accepts the key of SWR, and returns the data" - from here。我无法真正解释为什么你的代码 with fetcher 有效,但我分享了你修改后的代码,逻辑清晰。