Home > Enterprise >  Data fetched from Firebase using useSWR returns undefined
Data fetched from Firebase using useSWR returns undefined

Time:11-19

I am following a course where I am fetching data from Firebase using useSWR and using it to set the state. However when I try to console log the data, I get undefined and the screen shows loading. Is there any reason to this. I even copied the exact same code the instructor uses (except the 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;

CodePudding user response:

Accordingly to official docs -

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.

So it seemns that you simply don't pass any fetcher there.

Try defining hook like so:

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

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

CodePudding user response:

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

And your full file (working, tested by me):

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 don't use useEffect() hook (react hook) for data fetching, useSWR works perfect for this purpose.

P.S (2) you don't need fetcher to fetch data with no special params, so just = useSWR('/api/path')

Explanation about fetcher: if you check 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. I can't really explain why your code with fetcher works, but I shared your modified code with clear logic.

  • Related