【问题标题】:Data fetched from Firebase using useSWR returns undefined使用 useSWR 从 Firebase 获取的数据返回 undefined
【发布时间】:2023-03-07 05:37:01
【问题描述】:

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

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;

【问题讨论】:

  • 你是在全局定义 fetcher 方法吗?可以分享一下fetcher的代码吗?
  • 课程中没有提到全局添加 fetcher,所以我没有添加。但是添加一个 fetcher 函数似乎可以解决问题

标签: reactjs firebase firebase-realtime-database next.js


【解决方案1】:

根据官方文档-

useSWR 钩子接受一个密钥字符串和一个提取函数。 key 是数据的唯一标识符(通常是 API URL),将被传递给 fetcher。 fetcher 可以是任何返回数据的异步函数,你可以使用原生的 fetch 或 Axios 之类的工具。

所以看起来你根本没有在那里传递任何 fetcher。

尝试像这样定义钩子:

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

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

【讨论】:

  • OP 可能正在定义fetcher globally,否则他们会收到错误的抱怨。
  • 那么这个问题需要更多的上下文。
  • @JSEvgeny 添加一个 fetcher 似乎可以解决问题。我之前没有考虑添加它,因为教练说在这种情况下没有必要,因为它会默认使用 fetch 。在他的 GitHub 代码中也没有提及。
  • @JSEvgeny 你是对的,我是正确的。
【解决方案2】:
  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() 钩子(react 钩子)来获取数据,useSWR 非常适合此目的。

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

关于fetcher的说明:如果勾选official docs,则fetcher是可选参数。 “这里的 fetcher 是一个异步函数,它接受 SWR 的密钥,并返回数据”——来自here。我无法真正解释为什么您的代码使用 fetcher 可以工作,但我以清晰的逻辑分享了您修改后的代码。

【讨论】:

  • 你能解释一下为什么我的代码不起作用。我尝试添加一个 fetcher 函数,它似乎工作。但是,您刚刚说过不需要 fetcher 来获取数据。我有点失落
  • 已在帖子中回答
  • Fetcher 是可选的,因为 Note that fetcher can be omitted from the parameters if it's provided globally.,但必须以任何一种方式提供
猜你喜欢
  • 2022-01-22
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 2023-02-02
相关资源
最近更新 更多