Reputation: 116
I am practicing typescript with react and fetching some data from an API
I created a few days ago, API is working fine, am getting data for my front-end while fetching but when I try to use forEach or map method on that array of data it is throwing me an error:
Object is possibly 'undefined'
interface Posts {
_id: string
title: string
date: string
text: string
author_name: string
published: boolean
__v: number
}
const TextField = () => {
const [posts, setPosts] = useState<Posts>()
const fetchData = async () => {
const result = await fetch("https://ed-blog-api.herokuapp.com/api/posts")
const data = await result.json()
const posts = data.posts
setPosts(posts)
}
return (
<div>
<button onClick={fetchData}>Click</button>
{posts.forEach((post: object) => { // getting error here for posts
console.log(post)
})}
</div>
)
}
Upvotes: 0
Views: 3510
Reputation: 171
Full code
interface Posts {
_id: string;
title: string;
date: string;
text: string;
author_name: string;
published: boolean;
__v: number;
}
const TextField = () => {
const [posts, setPosts] = useState<Posts[]>([]);
const fetchData = async () => {
const result = await fetch('https://ed-blog-api.herokuapp.com/api/posts');
const data = await result.json();
const posts = data.posts;
setPosts(posts);
};
return (
<div>
<button onClick={fetchData}>Click</button>
{posts.map((post: Posts, index: number) => {
// getting error here for posts
console.log(post);
return <div key={index}>{JSON.stringify(post)}</div>;
})}
</div>
);
};
Make posts
an array. Then you can solve the loop error.
const [posts, setPosts] = useState<Posts[]>([]);
And I recommend to use map
instead of forEach
{posts.map((post: Posts, index: number) => {
console.log(post);
return <div key={index}>{JSON.stringify(post)}</div>;
})}
or (If you simply want to output only the component)
{posts.map((post: Posts, index: number) => (
<div key={index}>{JSON.stringify(post)}</div>
))}
Upvotes: 2
Reputation: 1802
I think your Posts
interface is actually the interface of a single Post
so:
interface Post {
_id: string
title: string
date: string
text: string
author_name: string
published: boolean
__v: number
}
type Posts=Post[]
Now in here, you don't need to type post
as object
anymore. Typescript will infer it itself.
const TextField = () => {
const [posts, setPosts] = useState<Posts|[]>([])
const fetchData = async () => {
const result = await fetch("https://ed-blog-api.herokuapp.com/api/posts")
const data = await result.json()
const posts = data.posts
setPosts(posts)
}
return (
<div>
<button onClick={fetchData}>Click</button>
{posts.forEach((post) => {
console.log(post)
})}
</div>
)
}
But actually the reason of that error, is that in JavaScript the type of null
is also object! so if you type anything as object
, you are saying it could be an array, object or null. if it is null, you can't use any properties of it.
Upvotes: 2
Reputation: 10264
Response
{
"posts": [{
"_id": "61514ba64209dbbaef9d05bb",
"title": "Valorant Sucks",
"date": "2021-09-27T04:40:05.001Z",
"text": "Valorant Sucks a lot, everytime I got fuccking smurf, not even a single bullet registering and lots of bugs and bugs",
"author_name": "Dev Chaudhary",
"published": true,
"__v": 0
}]
}
as the response that you used, the response.posts
is Array
.
so you should do like this.
const [posts, setPosts] = useState<Array<Posts>>([])
Futhermore,
return (
<div>
<button onClick={fetchData}>Click</button>
{posts.forEach((post) => { // you don't need to use `object` as type.
console.log(post)
})}
</div>
)
Upvotes: 2