typescript - Next js misslyckas vid byggnad med getStaticProps på grund av att param är undefined


ett konstigt fel började dyka upp som får byggnader att misslyckas,

vi har en post/[id].tsx-fil inuti vår pages-katalog, denna fil använder getStaticProps och getStaticPaths

-- rekvisita

export const getStaticProps: GetStaticProps = async ({ params }) => {
  const res: Response = await fetch(`${baseUrl}/api/products/${params.id}`);

  const data: Product[] = await res.json();

  return {
    props: {
      data,
    },
  };
};

-- stigar

export const getStaticPaths: GetStaticPaths = async () => {
  const res: Response = await fetch(`${baseUrl}/api/products`);
  const { data } = await res.json();

  const paths = data.map((product: Product) => ({
    params: { id: product.id.toString() },
  }));
  return { paths, fallback: "blocking" };
};

köra npm run dev lokalt och allt fungerar som förväntat, men när man kör npm run build uppstår felet

Type error: Object is possibly 'undefined'.

inne i getStaticProps-funktionen

> 12 |   const res: Response = await fetch(`${baseUrl}/api/products/${params.id}`);
                                                                      ^

Nu är det konstiga att den för närvarande distribuerade versionen på Vercel använder exakt samma kod för att bygga denna sida och inget har förändrats med den. Men nu börjar byggena plötsligt misslyckas?

Svar #1

Detta är en avknoppning av @Prantas svar ovan, med vissa ändringar. Medan Prantas lösning löser problemet i stor utsträckning, kommer Typescript att ge samma varning inom id-variabeldeklarationen, även om detta kanske inte orsakar att kompileringen misslyckas. Innan man går vidare är det viktigt att notera att varningen visas eftersom Nexts typdefinition för params-objektet är ParsedUrlQuery | undefined.

Ett sätt att lösa problemet och helt eliminera varningen är att ange typen på params-objektet till ParsedUrlQuery, så här:

// The import should happen automatically in VSCode, but if it doesn't
import { ParsedUrlQuery } from 'querystring';

const id = (params as ParsedUrlQuery).id;
const res: Response = await fetch(`${baseUrl}/api/products/${id}`);

Även om detta fungerar är det fortfarande inte den bästa lösningen. En bättre lösning, som jag rekommenderar, är att kontrollera att params-objektet faktiskt är definierat innan API-anropet görs i getStaticProps-funktionen. På så sätt kan du också undvika att stöta på problem i efterhand. Därför har vi:

if (params) {
  const id = params.id;
  const res: Response = await fetch(`${baseUrl}/api/products/${id}`);
}

Vi kan omstrukturera koden och lägga till en extra kontroll för att säkerställa att ett värde för id-vägparametern faktiskt hämtades från getStaticPaths-funktionen.

if (params && params.id) {
  const res: Response = await fetch(`${baseUrl}/api/products/${params.id}`);
}

Slutligen, eftersom getStaticProps-funktionen förväntar sig ett returvärde, måste vi specificera ett standardreturvärde som efterliknar strukturen av det returvärde som förväntas av funktionen, som visas nedan.

export const getStaticProps: GetStaticProps = async ({ params }) => {
  if (params && params.id) {
    const res: Response = await fetch(`${baseUrl}/api/products/${params.id}`);
    const data: Product[] = await res.json();
    return {
      props: { data },
    };
  }

  // Here, I'm returning an error property in the props object, but you can choose to return something else that suits your need.
  return {
    props: { error: true },
  };
};

Svar #2

Problemet här är att next.js gör en typkontroll här och typescript tror att dina parametrar kan vara odefinierade här. Berätta bara för typescript att de inte är det.

  const id = params.id!
  const res: Response = await fetch(`${baseUrl}/api/products/${id}`);

Detta borde fungera.

Relaterade artiklar