I have started my news project developing using React js. Unfortunately I have an issue. I am using axios for data fetching. I am making a request and I have an error in the console. I tried to use useState instead of variable posts in main file, but I had received the same error. I think, that something wrong either with posts variable, because I think, that useEffect is working slower, than html code, that will be returned or with map method.
Error:
TypeError: Cannot read properties of undefined (reading map) at news.jsx
Post file:
import React from 'react';
function Post(props) {
return (
<div className="post">
<div className="post-name">{props.title}</div>
<div className="post-content">{props.text}</div>
<a className="post-source" href={props.url}>{props.name}</a>
</div>
);
}
export default Post;
Main file with requests:
import React, { useEffect } from "react";
import SyncIcon from "@mui/icons-material/Sync";
import axios from "axios";
import "../css/news.css";
import Post from "./Post";
function News() {
let posts;
useEffect(() => {
const loading = document.querySelector(".loading");
const postsContainer = document.querySelector(".news-posts");
async function loadPosts() {
const date = new Date();
const day = date.getDate();
const month = date.getMonth();
const year = date.getFullYear();
const fullDate = year + "-0" + month + "-0" + day;
let response = [];
try {
const request = await axios.get(
`https://newsapi.org/v2/everything?qInTitle=Ukraine&from=${fullDate}&sortBy=publishedAt&apiKey=363858d3a88f49ffad9b467282270c8a`
);
const data = request.data.articles;
for (let i = 0; i < 20; i++) {
response.push({
source: {
name: data[i].source.name,
url: data[i].url,
},
content: {
title: data[i].title,
text: data[i].content,
},
});
}
} catch {
console.log("error");
}
loading.classList.add("none");
// setPosts(response);
posts = response;
}
loadPosts();
}, []);
return (
<section className="news-container">
<div className="news-posts">
<div className="loading">
<SyncIcon />
</div>
{posts.map((post) => (
<Post
name={post.source.name}
url={post.source.url}
text={post.content.text}
title={post.content.title}
/>
))}
</div>
</section>
);
}
export default News;
2
Answers
This is one of the proper ways to fetch data and display them:
Basically, the error is that your posts are undefined. And trying to map it breaks your app. You need to check if it exists and if it is an array, then map trough it. Also, the React way to render loading or error components is to use conditional rendering in the return function (check loading)
Also, you must use state otherwise React wont know if it needs to rerender anything.
You do not need to use query selectors
You should use
useState
for updating content in your component.The if statements I’ve implemented are in order to ensure the content received is not empty. You can remove those after you’ve debugged this or implement different actions under those conditions.