From 914b662455984b6b7dca50e5de56f3e0d0d4f134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Fri, 15 Sep 2023 12:22:51 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B4=80=EC=8B=AC=EB=AA=A9=EB=A1=9D=EC=97=90?= =?UTF-8?q?=20=EC=A3=BC=EC=8B=9D=EC=A0=95=EB=B3=B4=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?useCompanyData=20=ED=9B=85=20=EC=83=9D=EC=84=B1=20=EA=B8=B0?= =?UTF-8?q?=EC=97=85Id=EB=A5=BC=201=EB=B6=80=ED=84=B0=2014=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20=EB=AA=A8=EB=91=90=20=EC=82=BD=EC=9E=85=20=EC=84=B8?= =?UTF-8?q?=EB=A1=9C=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=20=EC=9D=B4=EB=A6=84=EC=9D=B4=20=EA=B4=80?= =?UTF-8?q?=EC=8B=AC=EB=AA=A9=EB=A1=9D=EC=9D=B8=20=EA=B2=83=EC=9D=84=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=AA=A9=EB=A1=9D=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=95=EC=A0=95=20=ED=95=84=EC=9A=94=20Issues=20#19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/watchlist/StockItem.tsx | 41 ++++++----- client/src/components/watchlist/WatchList.tsx | 69 +++++++++---------- client/src/hooks/useCompanyData.ts | 57 +++++++++++++++ 3 files changed, 114 insertions(+), 53 deletions(-) create mode 100644 client/src/hooks/useCompanyData.ts diff --git a/client/src/components/watchlist/StockItem.tsx b/client/src/components/watchlist/StockItem.tsx index 617b687e..fc2a0951 100644 --- a/client/src/components/watchlist/StockItem.tsx +++ b/client/src/components/watchlist/StockItem.tsx @@ -1,43 +1,50 @@ import React from 'react'; import styled from 'styled-components'; +import logo from '../../asset/logos/SK_logo.png' + + // StockItem 컴포넌트는 주식 정보를 나타내는 UI를 구성합니다. -const StockItem: React.FC = ({ stock, setShowChangePrice, showChangePrice }) => { +const StockItem: React.FC = ({ company, setShowChangePrice, showChangePrice }) => { return ( {/* 전체 아이템을 감싸는 래퍼 */} - {/* 로고 이미지 */} + {/* 로고 이미지 */} {/* 주식의 이름과 코드를 담는 섹션 */} - {stock.name} {/* 주식 이름 */} - {stock.code} {/* 주식 코드 */} + {company.korName} {/* 주식 이름 */} + {company.code} {/* 주식 코드 */} {/* 주식의 가격과 변동률을 담는 섹션 */} - {stock.price} {/* 주식 가격 */} - {company.stockPrice} + setShowChangePrice(true)} onMouseLeave={() => setShowChangePrice(false)} - > - {showChangePrice ? stock.changePrice : stock.change} {/* 변동률 또는 변동 가격 */} + > + {showChangePrice ? company.stockChangeAmount : company.stockChangeRate} {/* 변동률 또는 변동 가격 */} ); }; - type Stock = { - name: string; + + // 새로운 주식 데이터 형태 + type NewCompanyData = { + companyId: number; code: string; - price: string; - change: string; - changePrice: string; - logo: string; + korName: string; + stockPrice: string; // 현재가 + stockChangeAmount: string; // 변동량 + stockChangeRate: string; // 변동률 }; + // StockItem 컴포넌트에서 사용할 주식 데이터 형태 type StockItemProps = { - stock: Stock; - showChangePrice: boolean; + company: NewCompanyData; setShowChangePrice: React.Dispatch>; + showChangePrice: boolean; }; + const StockItemWrapper = styled.div` display: flex; diff --git a/client/src/components/watchlist/WatchList.tsx b/client/src/components/watchlist/WatchList.tsx index 73f22fbe..15420d03 100644 --- a/client/src/components/watchlist/WatchList.tsx +++ b/client/src/components/watchlist/WatchList.tsx @@ -2,58 +2,53 @@ import React, { useState } from 'react'; import styled from 'styled-components'; import Header from './Header'; import StockItem from './StockItem'; - -type WatchListProps = { - currentListType: "관심목록" | "투자목록"; - onChangeListType: (type: "관심목록" | "투자목록") => void; -}; +import useCompanyData from '../../hooks/useCompanyData'; const WatchList: React.FC = ({ currentListType, onChangeListType }) => { const [isMenuOpen, setMenuOpen] = useState(false); const [showChangePrice, setShowChangePrice] = useState(false); - // Sample stocks data - const stocks = [ - { - name: '삼성전자', - code: '005930', - price: '57800', - change: '+0.67%', - changePrice: '+380', - logo: 'https://your_logo_url.com' - }, - { - name: '현대차', - code: '005380', - price: '205000', - change: '-0.24%', - changePrice: '-500', - logo: 'https://your_logo_url.com' - }, - ]; + // useCompanyData 훅 사용하여 데이터 가져오기 + const { data: companies, isLoading, isError } = useCompanyData(1, 14); + + // 'companies'가 'undefined'인 경우를 처리하기 위해 빈 배열로 초기화 + const companiesList = companies || []; return ( -
- {stocks.map((stock, index) => ( - - ))} + {isLoading ? ( +
Loading...
+ ) : isError ? ( +
Error fetching data
+ ) : ( + companiesList.map((company) => ( + + )) + )}
); }; +// Props와 상태에 대한 타입 정의 +type WatchListProps = { + currentListType: '관심목록' | '투자목록'; + onChangeListType: (type: '관심목록' | '투자목록') => void; +}; + +// WatchList 컴포넌트에 대한 스타일드 컴포넌트 정의 const WatchListContainer = styled.div` display: flex; flex-direction: column; @@ -62,6 +57,8 @@ const WatchListContainer = styled.div` const StockList = styled.div` width: 100%; + max-height: 400px; /* 스크롤이 발생할 최대 높이를 지정하세요 */ + overflow-y: auto; /* 세로 스크롤을 활성화합니다 */ `; export default WatchList; diff --git a/client/src/hooks/useCompanyData.ts b/client/src/hooks/useCompanyData.ts new file mode 100644 index 00000000..5decdc9b --- /dev/null +++ b/client/src/hooks/useCompanyData.ts @@ -0,0 +1,57 @@ +import { useQuery } from 'react-query'; +import axios from 'axios'; + +const BASE_URL = 'http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080'; + +// 데이터 타입 정의 +type CompanyData = { + companyId: number; + code: string; + korName: string; + stockInfResponseDto: { + stck_prpr: string; + prdy_vrss: string; + prdy_ctrt: string; + }; +}; + +// 커스텀 훅 정의 +function useCompanyData(startCompanyId: number, endCompanyId: number) { + const fetchData = async (companyId: number) => { + const url = `${BASE_URL}/companies/${companyId}`; + const response = await axios.get(url); + return response.data; + }; + + // companyId 범위에 대한 배열 생성 + const companyIds = Array.from({ length: endCompanyId - startCompanyId + 1 }, (_, index) => startCompanyId + index); + + // 리액트-쿼리의 useQuery 훅 사용 + const { data, isLoading, isError } = useQuery( + ['companyData', startCompanyId, endCompanyId], + async () => { + const promises = companyIds.map((companyId) => fetchData(companyId)); + return Promise.all(promises); + } + ); + + // 필요한 데이터 추출 및 저장 + const extractedData = data?.map((company) => { + return { + companyId: company.companyId, + code: company.code, + korName: company.korName, + stockPrice: company.stockInfResponseDto.stck_prpr, + stockChangeAmount: company.stockInfResponseDto.prdy_vrss, + stockChangeRate: company.stockInfResponseDto.prdy_ctrt, + }; + }); + + return { + data: extractedData, + isLoading, + isError, + }; +} + +export default useCompanyData;