Búsqueda de sitios web

typescript - Next js falla en la compilación con getStaticProps debido a que el parámetro es indefinido


Empezó a aparecer un error extraño que está causando que las compilaciones fallen,

tenemos un archivo post/[id].tsx dentro de nuestro directorio pages, este archivo usa getStaticProps y getStaticPaths

-- props

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,
    },
  };
};

-- caminos

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" };
};

ejecutando npm run dev localmente y todo funciona como se espera, pero al ejecutar npm run build aparece el error

Type error: Object is possibly 'undefined'.

dentro de la función getStaticProps

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

Ahora lo extraño es que la versión actualmente desplegada en Vercel está usando exactamente el mismo código para construir esta página y nada ha cambiado en ella. ¿Pero ahora las compilaciones están fallando de repente?

Respuesta #1

Esto es una derivación de la respuesta de @Pranta arriba, con algunas modificaciones. Aunque la solución de Pranta resuelve el problema en gran medida, Typescript emitirá la misma advertencia dentro de la declaración de la variable id, aunque esto podría no causar que la compilación falle. Antes de continuar, es importante notar que la advertencia aparece porque la definición de tipos de Next para el objeto params es ParsedUrlQuery | undefined.

Una forma de resolver el problema y eliminar completamente la advertencia es asegurando el tipo del objeto params a ParsedUrlQuery, así:

// 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}`);

Aunque esto funciona, todavía no es la mejor solución. Una mejor solución, que recomiendo, es verificar que el objeto params esté realmente definido antes de hacer la llamada a la API en la función getStaticProps. De esta manera, también puedes evitar encontrarte con problemas posteriormente. Por lo tanto, tenemos:

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

Podemos refactorizar el código y agregar una verificación adicional para asegurarnos de que realmente se obtuvo un valor para el parámetro de ruta id de la función getStaticPaths.

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

Por último, dado que la función getStaticProps espera que se devuelva un valor, tenemos que especificar un valor de retorno por defecto que imite la estructura del valor de retorno que la función espera, como se muestra a continuación.

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 },
  };
};

Respuesta #2

El problema aquí es que next.js está haciendo una verificación de tipos y TypeScript piensa que tus parámetros podrían ser indefinidos aquí. Solo dile a TypeScript que no lo son.

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

Esto debería funcionar.

Artículos relacionados