Reputation: 67
I got the error:
Property 'title' does not exist on type 'never'. ..... console.log(blog.title);
But at the console of Browser I am able to see the "blog.title".
Here a screenshot from Browser
In this file I use the console.log and recieve the error:
const BlogDetails = () => {
const { id } = useParams<{ id: string }>();
const {
data: blog,
error,
isPending,
} = useFetch("http://localhost:8500/blogs/" + id);
console.log(blog&& blog.title);
return (
<div className="blog-details">
{isPending && <div>loading...</div>}
{error && <div>{error}</div>}
{blog && (
<article>
<h2>BlogDetails</h2>
</article>
)}
</div>
);
};
export default BlogDetails;
I use custom hook to fetch the Data:
import { useState, useEffect } from "react";
const useFetch = (url: string) => {
const [data, setData] = useState(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const abortCont = new AbortController();
setTimeout(() => {
fetch(url, { signal: abortCont.signal })
.then((res) => {
if (!res.ok) {
throw Error("could not fetch the data for that resource");
}
return res.json();
})
.then((data) => {
setIsPending(false);
setData(data);
setError(null);
})
.catch((err) => {
if (err.name === "AbortError") {
console.log("fetch aborted");
} else {
setIsPending(false);
setError(err.message);
}
});
}, 1000);
return () => abortCont.abort();
}, [url]);
return { data, isPending, error };
};
export default useFetch;
Upvotes: 2
Views: 512
Reputation: 192397
Typescript can't infer the types from an api call, so you'll need to provide them explicitly.
However, since useFetch
is a generic function, you'll need to add a type that fits the call, and pass it to the internal useState
. In addition, the initial value of useState
is null
, so we should also consider that.
We can add a generic type to useFetch
- <T>
, and type useState<T | null>()
to allow for the intended data type, and null
:
export const useFetch = <T>(url: string) => {
const [data, setData] = useState<T | null>(null);
To use it, you'll need to pass an explicit type to useFetch
. For example:
interface Data {
title: string;
body: string;
author: string;
id: number;
}
const { data: blog, error, isPending } = useFetch<Data>(
'http://localhost:8500/blogs/' + id
);
console.log(blog && blog.title); // or just console.log(blog?.title) with optional chaining
Whenever you call useFetch
you should provide it with the data type that fits the current response. For example:
useFetch<string[]>( // the result is an array of strings
useFetch<Data[]>( // the result is an array of data objects
useFetch<number>( // the result is a number
Upvotes: 3