react

React (axios로 API 호출 및 뉴스 가져오기)

소리소리솔소리 2022. 10. 19. 15:31

newsapi API 키 발급받기

이번 프로젝트에서는 newsapi에서 제공하는 API를 사용하여 최신 뉴스를 불러온 후 보여 줄 것이다.

 

https://newsapi.org/login?ReturnUrl=%2faccount 

 

Login - News API

 

newsapi.org

 

 

 

-components 폴더 생성

-NewsItems.js, NewsList.js 파일 생성

 

 

뉴스 뷰어 UI 만들기

NewsItem 만들기

각 뉴스 데이터가 지니고 있는 정보는 JSON 객체

-title : 제목

-description : 내용

-url : 링크

-urlToImage : 뉴스 이미지

-NewsItem 컴포넌트를 article 객체를 props로 통째로 받아서 사용

-a 태그의 rel 속성은 현재 문서와 링크 문서의 연관 관계를 명시 합니다.

-noreferrer : 사용자가 하이퍼링크를 클릭할 때 브라우저가 HTTP 리퍼러 헤더(referer header)를 전송해서는 안 됨을 나타냄.

-noopener : 하이퍼링크를 따라 연결되는 어떠한 브라우징 컨텍스트(browsing context)도 오프너(opener)여서는 안 됨을 나타냄.

 

NewsItems.js

import styled from 'styled-components';

const NewsItemBlock = styled.div`
    display: flex;
    margin-top: 3em;
    .thumbnail {
		margin-right: 1em;
		img {
			display: block;
			width: 160px;
			height: 100px;
			object-fit: cover;
		}
    }
    .contents {
	    h2 {
	    	margin: 0;
	    	a {
	    		color: black;
	    	}
	    }
	    p {
	    	margin: 0;
	    	line-height: 1.5;
	    	margin-top: 0.5rem;
	    	white-space: normal;
	    }
    }

`;
//NewsList로부터 한개의 기사단위로 컴포넌트를 호출 받음
const NewsItem = ({article}) => {
    const { title, description, url, urlToImage, source, author } = article; //구조 분해
    return (
        <NewsItemBlock>
            {urlToImage && (
                <div className='thumbnail'>
                    <a href={url} target="_black" rel="noopener noreferrer">
                        <img src={urlToImage} alt="thumbnail" />
                    </a>
                </div>
            )}
            <div className='contents'>
                <h2>
                    <a href={url} target="_blank" rel="noopener noreferrer">
                        {title}
                    </a>
                </h2>
                <p>{description}</p>
                <p>{source.name}</p>
                <p>{author}</p>
            </div>
        </NewsItemBlock>
    );
};
export default NewsItem;

 

 

 

NewsList.js

import axios from "axios";
import { useEffect, useState } from "react";
import { UNSAFE_DataRouterStateContext } from "react-router-dom";
import styled from "styled-components";
import NewsItem from "./NewsItems";

const NewsListBlock = styled.div`
    box-sizing: border-box;
    padding-bottom: 3em;
    width: 768px;
    margin: 0 auto;
    margin-top: 2rem;
    @media screen and (max-width: 768px) {
        width: 100%;
        padding-left: 1em;
        padding-right:1em;       
    }
`;

const NewsList = () => {
    const [articles, setArticles] = useState(null); 
    const [loading, setLoading] = useState(false);

    useEffect(() => { //화면이 렌더링 될 때 해야할 일을 여기서 구현
        const fetchData = async () => { //useEffect Hook에서 async/await를 사용하기 위해서는 함수가 필요
            setLoading(true); //화면이 로딩 중임을 표시 함
            try { //서버에 대한 요청을 시도 함
                const response = await axios.get(
                    "https://newsapi.org/v2/top-headlines?country=kr&apiKey=ffbbc82f694941a7b0e2d4f4515abcc7"
                );
                setArticles(response.data.articles); //동기처럼 보이지만 비동기로 결과를 받음, 랜더링이 일어남
                //console.log(response.data.articles);
            } catch (e) { //서버 요청이 실패 함
                console.log(e);
            }
            setLoading(false); 
        };
        fetchData();
    }, []); //[]의존성 배열을 의미, 
    //배열을 비워두면 값이 변경된 상태를 체크하지 않기 때문에 화면이 나타날 때만 
    //해당 함수가 실행 됨 

    if(loading) {
        return <NewsListBlock>로딩 중.........</NewsListBlock>
    }
    if(!articles) return null;

    return(
        <NewsListBlock>
            {/* 서버로부터 데이터가 들어오면 map 함수를 순회하는 매개변수를 전달 함*/}
            {articles.map(article =>(<NewsItem key={article.url} article={article}/>))}
        </NewsListBlock>
    )
}
export default NewsList;

 

 

App.js

import NewsList from "./components/NewsList";
const App = () => {
  return <NewsList />
};

export default App;

'react' 카테고리의 다른 글

React (useState 사용하기)  (0) 2022.10.21
CMD 창에서 프로젝트 생성하기  (0) 2022.10.21
React (뉴스 가져오기, Styled Components)  (0) 2022.10.19
React (router)  (0) 2022.10.19