728x90
이전 글
1. usePromise 커스텀 hook
이번에는 usePromise 훅을 프로젝트에 적용해보려 한다.
src 디렉토리 하단에 lib/usePromise 디렉토리 및 파일을 생성해준다.
- usePromise.js
기본 API 상태를 관리해줄 파일을 만들어준다.
promise 문을 사용하여 유틸 프로세스를 함수로 만들어서 재사용 할 수 있다.
APi 호출 시 사용한 loading, 성공시에 결과값을 받을 resolved, API 오류 발생 시 넘겨받을 error
3가지 타입의 state 를 선언해주자
대기: loading을 보여주고
완료: 응답값을 반환
실패: error 타입을 반환해준다
.
완료시에는 await로 API 결과값이 전달될떄까지 멈춘 후 resolved에 담긴다.
import { useState, useEffect } from "react";
export default function usePromise(promiseCreator, deps) {
// 대기 중/완료/실패/ 상태 관리하기
const [loading, setLoading] = useState(false);
const [resolved, setResolved] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const process = async () => {
setLoading(true);
try {
const resolved = await promiseCreator();
setResolved(resolved)
} catch (e) {
setError(e);
}
setLoading(false);
};
process();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps)
return [loading, resolved, error];
}
- NewsList.js
이제 작성한 usePromise 함수를 가져다가 기존 API 호출 방식과 교체해주자.
코드가 줄어들고 훨신 깔끔해진것을 볼 수 있다.
또한 공통 util을 사용함으로써 가독성과 코드의 통일성도 좋아진다.
import React from "react";
import styled from "styled-components";
import NewsItem from "./NewsItem"
import axios from "axios";
import usePromise from "../lib/usePromise";
const NewsItemBlock = 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 NewsList = ({category} ) => {
const [loading, response, error] = usePromise(() => {
// props로 넘어온 state로
const query = category === 'all' ? '' : `&category=${category}`;
return axios.get(
`https://newsapi.org/v2/top-headlines?country=kr${query}&apiKey=afda249a1ccb482fa0944d12a295021b`,
)
}, [category])
// 대기 중
if (loading) {
return <NewsItemBlock>대기 중입니다...</NewsItemBlock>
}
// articles 값이 설정 안될경우 (null 오류방지)
if (!response) {
return null;
}
// 에러가 발생했을 떄
if (error) {
return <NewsItemBlock>에러 발생...</NewsItemBlock>;
}
const { articles } = response.data;
return (
<NewsItemBlock>
{articles.map(v => (
<NewsItem key={v.url} article={v} />
))}
</NewsItemBlock>
);
};
export default React.memo(NewsList);
2. 최종 프로젝트 결과물
728x90
'프론트엔드 > React' 카테고리의 다른 글
[프론트엔드] REACT+MOBX 슈퍼마켓 구현 (0) | 2022.03.30 |
---|---|
[프론트엔드] "npm run start" = "react-scripts: Permission denied" 문제 해결 (0) | 2022.03.30 |
[프론트엔드] REACT 뉴스 뷰어 만들기 [8] (0) | 2022.03.26 |
[프론트엔드] REACT 뉴스 뷰어 만들기 [7] (0) | 2022.03.26 |
[프론트엔드] REACT 뉴스 뷰어 만들기 [6] (0) | 2022.03.26 |