아래 코드에서 가장 중요한 부분은 아직 api를 불러와서 articles가 set되지 않았을 때! 즉, articles 상태가 null일 때다. 이 때를 위해서 if문으로 articles가 false인 상태를 처리해줘야 한다.
useEffect 의존에 빈 배열을 줬을 때 컴포넌트가 로드되면서 최초로 실행되게 하는 것으로 알고있는데 이 때 api를 불러와서 articles가 set되고 렌더링이 될 것이라고 착각했다. 하지만, 이번 경험을 통해 실제 렌더링이 먼저 이루어지고 useEffect에 빈배열을 준 hook이 동작한다는 것을 알았다.
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import axios from 'axios';
import NewsItem from './NewsItem';
const NewsListBlock = styled.div`
width: 768px;
margin: 0 auto;
margin-top: 2rem;
`;
export default function NewsList() {
const [articles, setArticles] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const response = await axios.get(
'https://newsapi.org/v2/top-headlines?country=kr&apiKey=29a0160871334cf6861f6fb96d4f86c4'
);
console.log(response.data.articles);
setArticles(response.data.articles);
} catch (e) {
console.log(e);
}
setLoading(false);
};
fetchData();
}, []);
if (loading) {
return <p>로딩중</p>;
}
if (!articles) {
return null;
}
return (
<NewsListBlock>
{articles.map(article => (
<NewsItem key={article.url} article={article} />
))}
</NewsListBlock>
);
}
한 줄 요약
component 렌더링이 먼저 되고 useEffect가 동작한다. 받아오는 상태로 map을 돌리는 상태라면 아직 null일 때 map이 돌 수 없어서 오류가 발생한다. 그러니까 useEffect에서 api를 호출중일 때를 위해서 if(!articles) return null이 필요하다.