Reputation: 489
weird error started appearing that's causing builds to fail,
we have a post/[id].tsx file inside of our pages dir, this file uses getStaticProps
and 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,
},
};
};
-- paths
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" };
};
running npm run dev
locally and everything works as expected, but running npm run build
and the error
Type error: Object is possibly 'undefined'.
inside of the getStaticProps function
> 12 | const res: Response = await fetch(`${baseUrl}/api/products/${params.id}`);
^
Now the weird thing is that the currently deployed build on vercel is using the exact same code to build this page and nothing has changed from it. But now builds are suddenly failing?
Upvotes: 5
Views: 4135
Reputation: 71
This is an offshoot of @Pranta's answer above, with some modifications. While Pranta's solution solves the problem to a great extent, Typescript will issue the same warning within the id
variable declaration, although this might not cause the build to fail. Before moving on, it's important to note that the warning shows up because Next's type definition for the params
object is ParsedUrlQuery | undefined
.
One way to resolve the issue and completely eliminate the warning is by asserting the type of the params
object to ParsedUrlQuery
, like this:
// 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}`);
While this works, it is still not the best solution. A better solution, which I recommend, is checking that the params
object is actually defined before making the API call in the getStaticProps
function. This way, you can also avoid running into issues subsequently. Hence, we have:
if (params) {
const id = params.id;
const res: Response = await fetch(`${baseUrl}/api/products/${id}`);
}
We can refactor the code and add an extra check to ensure that a value for the id
path parameter was actually retrieved from the getStaticPaths
function.
if (params && params.id) {
const res: Response = await fetch(`${baseUrl}/api/products/${params.id}`);
}
Lastly, because the getStaticProps
function expects a value to be returned, we have to specify a default return value that mimics the structure of the return value expected by the function, as seen below.
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 },
};
};
Upvotes: 7
Reputation: 3695
The problem here is that next.js is doing a type-check here and typescript thinks your params might be undefined here. Just tell typescript it's not.
const id = params.id!
const res: Response = await fetch(`${baseUrl}/api/products/${id}`);
This should work.
Upvotes: 2