Data fetching twice in Next13.
Unanswered
Vikhan posted this in #help-forum
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,
Here's the console output,
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 undefined32 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
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
@Marchy it renders as static for me
notice the
params in CompanyPage. It needs to be app/something/[companyName]/page.tsx@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.companyNamethat's also why you are seeing a bunch of
undefined in that logbut 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 repositorythat's interesting
try
nordea (known company from the original question) instead of asdfi 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 emptywait how is that possible, how do you not have the log from
CompanyInfooh heck I changed that 🤦â€â™‚ï¸
yeah then everything still works like expected and we don't have this confusing
COMPANY NAME null
DATA []
COMPANY undefinedhow 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
