Next.js Discord

Discord Forum

Data fetching twice in Next13.

Unanswered
Vikhan posted this in #help-forum
Open in Discord
VikhanOP
Hey guys! New to Next13 and just playing around. I wanted to try to do fetch from my API, but it seems to be fetching twice. First fetch is successful, but the other one just fails? I'm pretty lost, couldn't find anything online so I'll try here.

Here's my code,
import { Suspense } from "react";

async function getCompany(companyName) {
  console.log("COMPANY NAME", companyName);
  const response = await fetch(
    `https://placerai-1b8aaf5f116c.herokuapp.com/getCompanies?companyName=${companyName}`
  );

  if (!response.ok) {
    throw new Error("Error fetching data");
  }

  const data = await response.json();

  console.log("DATA", data);

  return data[0];
}

const CompanyInfo = async ({ companyPromise }) => {
  const company = await companyPromise;

  console.log("COMPANY", company);

  return (
    <div className="md:container sm:mx-auto">
      <h1>{company?.name}</h1>
    </div>
  );
};

export default async function CompanyPage({ params }) {
  const companyData = getCompany(params.companyName);

  return (
    <Suspense fallback="loading...">
      <CompanyInfo company={companyData} />
    </Suspense>
  );
}

Here's the console output,
COMPANY NAME nordea
DATA [
  {
    instrument: null,
    ....
  }
]
COMPANY undefined
COMPANY NAME null
DATA []
COMPANY undefined

32 Replies

This is expected behavior

Your fetch happens once on the server to pre-render content, then once on the client once it hits the browser. If you want to make sure this only happens in the server, you'd need to 'use server' in your getCompany function
no i'm pretty sure server components rendering logic isn't rerun in the browser
oh there's no await
const companyData = getCompany(params.companyName);
so "await fetch data.json" is getting passed back into the function, which is read as client code no?
i think CompanyInfo which awaits the promise is still a server component
@joulev i think `CompanyInfo` which awaits the promise is still a server component
If you don't explicitly define 'use server' it would default to static if it can
here the page is dynamically rendered because it is a dynamic route without generateStaticParams
@Vikhan Hey guys! New to Next13 and just playing around. I wanted to try to do fetch from my API, but it seems to be fetching twice. First fetch is successful, but the other one just fails? I'm pretty lost, couldn't find anything online so I'll try here. Here's my code, jsx import { Suspense } from "react"; async function getCompany(companyName) { console.log("COMPANY NAME", companyName); const response = await fetch( `https://placerai-1b8aaf5f116c.herokuapp.com/getCompanies?companyName=${companyName}` ); if (!response.ok) { throw new Error("Error fetching data"); } const data = await response.json(); console.log("DATA", data); return data[0]; } const CompanyInfo = async ({ companyPromise }) => { const company = await companyPromise; console.log("COMPANY", company); return ( <div className="md:container sm:mx-auto"> <h1>{company?.name}</h1> </div> ); }; export default async function CompanyPage({ params }) { const companyData = getCompany(params.companyName); return ( <Suspense fallback="loading..."> <CompanyInfo company={companyData} /> </Suspense> ); } Here's the console output, COMPANY NAME nordea DATA [ { instrument: null, .... } ] COMPANY undefined COMPANY NAME null DATA [] COMPANY undefined
i can't reproduce this. can you make a minimal reproduction repository? i only see one fetch in my log
COMPANY NAME nordea
DATA [
  {
    instrument: null,
    profile: null,
    group: null,
    currency: null,
    company: {
      id: 'ac5661db-8f08-4e68-a719-f0bb012d19af',
      slug: 'nordea',
      name: 'Nordea Bank',
      description: 'Nordea conducts banking operations. The bank offers a wide range of financial services, aimed at both private and corporate customers, including traditional asset management, loan financing, and pension savings. In addition, advice and security insurance are also offered, as well as currency management. Nordea conducts most of its business in the Nordic and Baltic countries. The company was founded in 1997 and the head office is located in Helsinki.',
      country: 'FI',
      image_url: 'https://lh3.googleusercontent.com/7Wclw4ulNYJNnIIumd6TtyLcl9tDwiyTBsnq94QypM7qvPAAr9SEb6-Yn7778m4y9CSJquBfhqXOJXM5r-mV6az2q6--oyoihmAo42Q',
      website: 'https://www.nordea.com/en/investors',
      follower_count: 251,
      owner_count: 0,
      morningstar_sector: [Object],
      morningstar_industry: [Object],
      client_url: null
    },
    rank: '0.6079',
    score: '0.6079'
  }
]
COMPANY {
  instrument: null,
  profile: null,
  group: null,
  currency: null,
  company: {
    id: 'ac5661db-8f08-4e68-a719-f0bb012d19af',
    slug: 'nordea',
    name: 'Nordea Bank',
    description: 'Nordea conducts banking operations. The bank offers a wide range of financial services, aimed at both private and corporate customers, including traditional asset management, loan financing, and pension savings. In addition, advice and security insurance are also offered, as well as currency management. Nordea conducts most of its business in the Nordic and Baltic countries. The company was founded in 1997 and the head office is located in Helsinki.',
    country: 'FI',
    image_url: 'https://lh3.googleusercontent.com/7Wclw4ulNYJNnIIumd6TtyLcl9tDwiyTBsnq94QypM7qvPAAr9SEb6-Yn7778m4y9CSJquBfhqXOJXM5r-mV6az2q6--oyoihmAo42Q',
    website: 'https://www.nordea.com/en/investors',
    follower_count: 251,
    owner_count: 0,
    morningstar_sector: {
      id: 103,
      name: 'sector_financial_services',
      key: 'sector_financial_services',
      description: 'sector_description_financial_services',
      description_key: 'sector_description_financial_services',
      slug: 'financial-services',
      super_sector_key: 'super_sector_cyclical',
      super_sector_description_key: 'super_sector_description_cyclical',
      image: null
    },
    morningstar_industry: {
      id: 10320020,
      name: 'Banks—Regional',
      key: 'industry_banks_regional',
      slug: 'banks-regional'
    },
    client_url: null
  },
  rank: '0.6079',
  score: '0.6079'
}
i think you somehow are running this in two places and nextjs is not detecting that it needs to deduplicate the request
it renders as static for me
@Marchy it renders as static for me
notice the params in CompanyPage. It needs to be app/something/[companyName]/page.tsx
@joulev notice the `params` in `CompanyPage`. It needs to be `app/something/[companyName]/page.tsx`
It's still querying 3 times on build
@Marchy It's still querying 3 times on build
yes but well it is not relevant right? because the page here must be a dynamic route page with [companyName] because otherwise why is the OP even using params.companyName
that's also why you are seeing a bunch of undefined in that log
@joulev i can't reproduce this. can you make a minimal reproduction repository? i only see one fetch in my log tsx COMPANY NAME nordea DATA [ { instrument: null, profile: null, group: null, currency: null, company: { id: 'ac5661db-8f08-4e68-a719-f0bb012d19af', slug: 'nordea', name: 'Nordea Bank', description: 'Nordea conducts banking operations. The bank offers a wide range of financial services, aimed at both private and corporate customers, including traditional asset management, loan financing, and pension savings. In addition, advice and security insurance are also offered, as well as currency management. Nordea conducts most of its business in the Nordic and Baltic countries. The company was founded in 1997 and the head office is located in Helsinki.', country: 'FI', image_url: 'https://lh3.googleusercontent.com/7Wclw4ulNYJNnIIumd6TtyLcl9tDwiyTBsnq94QypM7qvPAAr9SEb6-Yn7778m4y9CSJquBfhqXOJXM5r-mV6az2q6--oyoihmAo42Q', website: 'https://www.nordea.com/en/investors', follower_count: 251, owner_count: 0, morningstar_sector: [Object], morningstar_industry: [Object], client_url: null }, rank: '0.6079', score: '0.6079' } ] COMPANY { instrument: null, profile: null, group: null, currency: null, company: { id: 'ac5661db-8f08-4e68-a719-f0bb012d19af', slug: 'nordea', name: 'Nordea Bank', description: 'Nordea conducts banking operations. The bank offers a wide range of financial services, aimed at both private and corporate customers, including traditional asset management, loan financing, and pension savings. In addition, advice and security insurance are also offered, as well as currency management. Nordea conducts most of its business in the Nordic and Baltic countries. The company was founded in 1997 and the head office is located in Helsinki.', country: 'FI', image_url: 'https://lh3.googleusercontent.com/7Wclw4ulNYJNnIIumd6TtyLcl9tDwiyTBsnq94QypM7qvPAAr9SEb6-Yn7778m4y9CSJquBfhqXOJXM5r-mV6az2q6--oyoihmAo42Q', website: 'https://www.nordea.com/en/investors', follower_count: 251, owner_count: 0, morningstar_sector: { id: 103, name: 'sector_financial_services', key: 'sector_financial_services', description: 'sector_description_financial_services', description_key: 'sector_description_financial_services', slug: 'financial-services', super_sector_key: 'super_sector_cyclical', super_sector_description_key: 'super_sector_description_cyclical', image: null }, morningstar_industry: { id: 10320020, name: 'Banks—Regional', key: 'industry_banks_regional', slug: 'banks-regional' }, client_url: null }, rank: '0.6079', score: '0.6079' }
if you make a [companyName] page though and build it in prod mode and use nordea as the params when testing it, you will see this log
but the two fetches one for nordea one for null is interesting...
not undefined but null - that's something i don't understand yet and needs a clone-able reproduction repository
actually, this checks out. There's 2 console logs, even though CompanyInfo isn't used :meow_stare:
that's interesting
try nordea (known company from the original question) instead of asdf
i get
COMPANY NAME nordea
DATA <json>
COMPANY <json>
the reason the page is blank is that that huge object doesn't have ?.name so the h1 is empty
@joulev try `nordea` (known company from the original question) instead of `asdf`
wait how is that possible, how do you not have the log from CompanyInfo
oh heck I changed that 🤦‍♂️
yeah then everything still works like expected and we don't have this confusing
COMPANY NAME null
DATA []
COMPANY undefined
how can a dynamic route param be null
<CompanyInfo companyPromise={companyData} />
Was it running as a seperate function because of the param difference?
the way the OP did it sure is strange, i'm not sure if it would work but i don't have any ideas why it would fail either. @Vikhan I prefer this way which doesn't pass promises and looks clearer
import { Suspense } from "react";

async function getCompany(companyName: string) {
  console.log("COMPANY NAME", companyName);
  const response = await fetch(
    `https://placerai-1b8aaf5f116c.herokuapp.com/getCompanies?companyName=${companyName}`
  );

  if (!response.ok) {
    throw new Error("Error fetching data");
  }

  const data = await response.json();

  console.log("DATA", data);

  return data[0];
}

const CompanyInfo = async ({ companyName }: { companyName: string }) => {
  const companyData = await getCompany(companyName);

  console.log("COMPANY", companyData);

  return (
    <div className="md:container sm:mx-auto">
      <h1>{companyData?.name}</h1>
    </div>
  );
};

export default async function CompanyPage({
  params,
}: {
  params: { companyName: string };
}) {
  return (
    <Suspense fallback="loading...">
      <CompanyInfo companyName={params.companyName} />
    </Suspense>
  );
}
 <Suspense fallback="loading...">
      <CompanyInfo company={companyData} /> // <---
    </Suspense>

this is the cause of the extra api call