서버쪽 데이터를 받아올 때는 API를 호출함으로 써 데이터를 수신하는데
이 과정에서 시간이 걸리기 때문에 이 작업을 비동기적으로 처리하게 된다.
비동기 작업을 할 때 가장 흔히 사용하는 방법
콜백 지옥을 예방하기 위해 나온 기능
Promise를 더 쉽게 사용할 수 있도록 하는 문법
함수 앞에 async 키워드를 추가하고 Promise 앞부분에 await 를 사용
$ yarn create react-app news-viewer
$ yarn add axios
코드 스타일 자동으로 정리하기
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
파일 자동 불러오기를 잘 활용하고 싶다면
{
"compilerOptions": {
"target": "ES6"
}
}
import axios from 'axios';
import {useState} from 'react'
import './App.css';
const App = () => {
const [data,setData] = useState(null)
const onClick= ()=>{
axios.get('https://jsonplaceholder.typicode.com/todos/1').then(response=>{
setData(response.data)
})
}
return (
<div>
<div><button onClick={onClick}>불러오기</button></div>
{data && <textarea rows={7} value={JSON.stringify(data,null,2)} readOnly={true} />}
</div>
)
}
export default App;
const [data,setData] = useState(null)
빈 data를 만들어놓는다
onClick
하게 된다면
axios.get('https://jsonplaceholder.typicode.com/todos/1')
주소로 axios 요청을 보내 API를 호출하게 되고 ('GET')
.then(response=>{setData(response.data)})
값을 받는데 성공하면 data의 값을 response 내용으로 바꾼다 (비동기적)
{data && <textarea rows={7} value={JSON.stringify(data,null,2)} readOnly={true} />}
data 가 null이 아니면 출력을 한다.
const onClick= async ()=>{
try{
const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1')
setData(response.data)
}
catch(e){
console.log(e)
}
}
사전 API 발급받기 : https://newsapi.org/register/success
내 API 키 : 755b48e892b34cab8c2f6f7be92d8944
한국 뉴스 가져오는 API 설명서 : https://newsapi.org/s/south-korea-news-api
전체 뉴스 불러오기
https://newsapi.org/v2/top-headlines?**country=kr**&apiKey=755b48e892b34cab8c2f6f7be92d8944
특정 카테고리 불러오기
try{
const response = await axios.get('https://newsapi.org/v2/top-headlines?country=kr&category=sports&apiKey=755b48e892b34cab8c2f6f7be92d8944')
setData(response.data)
}
현재 api 정보 확인하기
$ yarn add styled-component
사용 법 ⇒ 컴포넌트 변수로 만든다. styled
불러온 뒤 백틱으로 묶고 css 설정 해준 뒤
사용시 <컴포넌트> </컴포넌트>
사이에 적으면 styling 완료
import styled from "styled-components";
const NewsItemBlock = styled.div`
display:flex
.thumbnail{
margin-right:1rem;
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;
}
}
&+&{
margin-top:3rem;
}
`;
const NewsItem =({article})=>{
const {title,description,url,urlToImage} = article
return (
<NewsItemBlock>
{urlToImage && (
<div className="thumbnail">
<a href={url} target="_blank" rel="nooperner noreferrer">
<img src={urlToImage} alt="thumbnail"/>
</a>
</div>
)}
<div className="contents">
<h2>
<a href={url} target="_blank" rel="nooperner noreferrer">
{title}
</a>
</h2>
<p>{description}</p>
</div>
</NewsItemBlock>
)
}
export default NewsItem;
리스트에서 Item들 보여주기
import styled from "styled-components";
import NewsItem from "./NewsItem";
const NewsListBlock = styled.div`
box-sizing:border-box;
padding-bottom:3rem;
width:768px;
margin:0 auto;
margin-top:2rem;
@media screen and (max-width:768){
width:100%;
padding-left:1rem;
padding-right:1rem
}
`;
const sampleArticle = {
title:'제목',
description:'내용',
url :'https://google.com',
urlToImage : 'https://via.placeholder.com/160',
}
const NewsList = ()=>{
return (
<NewsListBlock>
<NewsItem article={sampleArticle}/>
<NewsItem article={sampleArticle}/>
<NewsItem article={sampleArticle}/>
<NewsItem article={sampleArticle}/>
<NewsItem article={sampleArticle}/>
<NewsItem article={sampleArticle}/>
</NewsListBlock>
)
}
export default NewsList
<NewsList/>
불러오기
useEffect
사용해서 컴포넌트가 처음 렌더링되는 시점에 API를 요청하면 된다.
import styled from "styled-components";
import NewsItem from "./NewsItem";
import { useState,useEffect } from "react";
import axios from "../../../node_modules/axios/index";
const 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&category=sports&apiKey=755b48e892b34cab8c2f6f7be92d8944'
)
setArticles(response.data.articles)
}catch(e){
console.log(e)
}
setLoading(false)
}
fetchData();
},[])
if(loading){
return <NewsListBlock>대기중...</NewsListBlock>
}
if(!articles){
return null
}
return (
<NewsListBlock>
{articles.map(article=>(
<NewsItem key={article.url} article={article} />
))}
</NewsListBlock>
)
}
export default NewsList
if(!articles){return null }
map 함수를 쓰기 전에 꼭 !articles를 조회하여 해당값이 현재 null인지 검사해야 한다.
아직 데이터가 없을 떄 null에는 map 함수가 없기 때문에 렌더링 과정에서 오류 발생한다.