[React]외부 API 연동하여 뉴스 뷰어 만들어보기-1

UkiUkhui·2021년 10월 24일
0

React 공부중

목록 보기
18/25

1. 비동기 작업의 이해

1.1. 콜백 함수

function printMe() {
console.log('Hello World!');
}
setTimeout(printMe, 3000);
console.log('대기 중...'); 
  • setTimeout의 인자로 넘겨준 함수 = 콜백함수
function increase(number, callback) {
setTimeout(() => {
  const result = number + 10;
  if (callback) {
    callback(result);
  }
}, 1000);
}
 
console.log('작업 시작');
increase(0, result => {
console.log(result);
increase(result, result => {
  console.log(result);
  increase(result, result => {
    console.log(result);
    increase(result, result => {
      console.log(result);
      console.log('작업 완료');
    });
  });
});
});
  • 콜백지옥

1.2. 프로미스

function increase(number) {
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const result = number + 10;
    if (result > 50) {
      const e = new Error('NumberTooBig');
      return reject(e);
    }
    resolve(result); 
  }, 1000);
});
return promise;
}
 
increase(0)
.then(number => {
  console.log(number);
  return increase(number); 
})
.then(number => {
  console.log(number);
  return increase(number);
})
.then(number => {
  console.log(number);
  return increase(number);
})
.then(number => {
  console.log(number);
  return increase(number);
})
.then(number => {
  console.log(number);
  return increase(number);
})
.catch(e => {
  console.log(e);
});
  • resolve : 성공, reject : 실패
  • .then을 통해 그 다음 작업을 설정

1.3. async/await

function increase(number) {
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const result = number + 10;
    if (result > 50) { 
      const e = new Error(‘NumberTooBig‘);
              return reject(e);
    }
          resolve(result);
  }, 1000)
});
return promise;
}


async function runTasks() {
try { 
  let result = await increase(0);
  console.log(result);
  result = await increase(result);
  console.log(result);
  result = await increase(result);
  console.log(result);
  result = await increase(result);
  console.log(result);
  result = await increase(result);
  console.log(result);
  result = await increase(result);
  console.log(result);
} catch (e) {
  console.log(e);
}
}

2.axios로 API 호출해서 데이터 받아오기

  • HTTP 요청을 Promise 기반으로 처리함
import axios from "axios";
import { useState } from "react";
import "./styles.css";

export default function App() {
  const [data, setData] = useState(null);
  const onClick = ()=>{
    axios.get('https://jsonplaceholder.typicode.com/todos/1')
    .then(res=>{setData(res.data)})
  }
  return (
    <div>
      <button onClick={onClick}>불러오기</button>
      {data&&<textarea value={JSON.stringify(data, null, 2)}/>}
    </div>
  );
}
  • 버튼을 누르면 API를 호출하고 이에 대한 응답을 컴포넌트 state에 넣어줌.
  • 주소에 GET 요청 후, .then을 통해 처리
  const [data, setData] = useState(null);
  // const onClick = ()=>{
  //   axios.get('https://jsonplaceholder.typicode.com/todos/1')
  //   .then(res=>{setData(res.data)})
  // }
  const onClick = async()=>{
    try{
      const res = await axios.get("'https://jsonplaceholder.typicode.com/todos/1'");
      setData(res.data);
    }catch(e){
      console.log(e);
    }

async/await 이용 시 좀더 직관적으로 볼 수 있음

3. newsAPI Key 받아오기

https://newsapi.org/s/south-korea-business-news-api
참조

4. NewsViewer UI 만들기

4.1. NewsItems

import React from "react";
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 NewsItems = ({ article }) => {
    const { title, description, url, urlToImage } = article;
    return (
        <NewsItemBlock>
            {urlToImage && (
                <div className="thumbnail">
                    <a href={url} target="_blank" rel="noopener noreferrer">
                        <img src={urlToImage} alt="thumbnail" />
                    </a>

                </div>
            )}
            <div className="content">
                <h2>
                    <a href={url} target="_blank" rel="noopener noreferrer">
                        {title}
                    </a>
                </h2>
                <p>
                    {description}
                </p>
            </div>
        </NewsItemBlock>
    )
}

export default NewsItems;
  • 뉴스 데이터의 title, description, url, urlToImage만 받아와서 보여줌.
  • article이라는 props를 통해 JSON을 통째로 받아와 필요한 데이터만 사용할 것

a 태그

  • href : 링크된 페이지의 url
  • target : 링크된 페이지 클릭 시 문서가 열릴 위치 표시
    -_blank : 새로운 윈도우나 탭에서 오픈함
  • rel : 현재 문서와 대상 url의 관계 명시
    -noopener: 하이퍼링크를 따라 연결되는 어떠한 브라우징 컨텍스트(browsing context)도 오프너(opener)여서는 안 됨을 나타냄.
    -noreferrer:사용자가 하이퍼링크를 클릭할 때 브라우저가 HTTP 리퍼러 헤더(referer header)를 전송해서는 안 됨을 명시함.

4.2. NewsList.js

import React from "react";
import styled from "styled-components";
import NewsItems from "./NewsItems";

const NewsListBlock = styled.div`
  box-sizing: border-box;
  padding-bottom: 3rem;
  width: 768px;
  margin: 0 auto;
  margin-top: 2rem;
  @media screen and (max-width: 768px) {
    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>
            <NewsItems article={sampleArticle} />
            <NewsItems article={sampleArticle} />
            <NewsItems article={sampleArticle} />
            <NewsItems article={sampleArticle} />
        </NewsListBlock>
    );
};

export default NewsList;
  • 아직 데이터를 받아오기 전이므로 url 부분은 아무런 데이터로 채워줬음
profile
hello world!

0개의 댓글

관련 채용 정보