Skip to content

Commit

Permalink
[Feat] 차트 상단 종목개요 refetching 로직 추가
Browse files Browse the repository at this point in the history
- 중앙 차트 상단의 종목 개요부분 서버 데이터 갱신 주기에 맞춰서 refetching 되는 로직 추가
- 정각/30분 기준으로 API 재요청하며, 서버 데이터 갱신주기는 30분이나 서버-클라이언트 시간 불일치할 가능성 고려하여 재요청 주기 10분으로 설정 (추후 수정 가능)

Issues #14
  • Loading branch information
novice1993 committed Sep 7, 2023
1 parent 23579b5 commit a2a6cb7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 26 deletions.
2 changes: 1 addition & 1 deletion client/src/components/CentralChart/KospiChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const KospiChart = () => {
};

const handlePressEmnterToSearch = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.code === "Enter") {
if (e.code === "Enter" && e.nativeEvent.isComposing === false) {
handleSearchCompany();
setSearchWord("");
}
Expand Down
20 changes: 11 additions & 9 deletions client/src/components/CentralChart/StockChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const loadingText = "로딩 중 입니다...";
const errorText = "화면을 불러올 수 없습니다";

//🔴 테스트
import { useEffect, useState } from "react";
import { useState } from "react";

const StockChart = () => {
const companyId = useSelector((state: StateProps) => state.companyId);
Expand All @@ -26,14 +26,16 @@ const StockChart = () => {
// 🔴 차트 변환 테스트

// 🔴 1) 검색 이벤트
const { companyList } = useGetCompanyList();
const [companyLists, setCompanyLists] = useState([]);
const { companyList, compnayListLoading, companyListError } = useGetCompanyList();
const [searchWord, setSearchWord] = useState("");

// 회사 목록 불러오면 -> companyList 상태에 할당
useEffect(() => {
setCompanyLists(companyList);
}, [companyList]);
if (compnayListLoading) {
return <p>회사정보 불러오는 중</p>;
}

if (companyListError) {
return <p>에러 발생</p>;
}

const handleChangeSearchWord = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearchWord(e.target.value);
Expand All @@ -42,7 +44,7 @@ const StockChart = () => {
const handleSearchCompany = () => {
let searchResult: string = "noExistCompany";

companyLists.forEach((company: CompanyProps) => {
companyList.forEach((company: CompanyProps) => {
if (company.korName === searchWord) {
searchResult = "ExistCompany";
dispatch(changeCompanyId(company.companyId));
Expand All @@ -55,7 +57,7 @@ const StockChart = () => {
};

const handlePressEmnterToSearch = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.code === "Enter") {
if (e.code === "Enter" && e.nativeEvent.isComposing === false) {
handleSearchCompany();
setSearchWord("");
}
Expand Down
47 changes: 36 additions & 11 deletions client/src/components/CentralChartMenu/StockOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,37 @@ const StockOverview = () => {
return <p>에러 발생</p>;
}

const corpName = data.korName;
const stockCode = data.code;
const stockPrice = parseInt(data.stockInfResponseDto.stck_prpr, 10).toLocaleString();
const priceChageRate = parseFloat(data.stockInfResponseDto.prdy_ctrt);
const chageDirection = priceChageRate > 0 ? "▲" : "▼";
const priceChageAmount = Math.abs(parseInt(data.stockInfResponseDto.prdy_vrss, 10)).toLocaleString();
const transactionVolume = parseInt(data.stockInfResponseDto.acml_vol, 10).toLocaleString();
// 총 거래대금 계산
const amount = parseInt(data.stockInfResponseDto.acml_tr_pbmn, 10);
const [billions, tenThousands] = [Math.floor(amount / 100000000), Math.floor((amount % 100000000) / 10000)];
const transactionValue = `${billions.toLocaleString()}${tenThousands.toLocaleString()}만`;

return (
<Container>
<Container priceChangeRate={priceChageRate}>
<img className="CorpLogo" src={dummyData.corpLogo} />
<div className="CorpName">{data.korName}</div>
<div className="CorpName">{corpName}</div>
<div className="StockCode">
{data.code} <span>{marketType}</span>
{stockCode} <span>{marketType}</span>
</div>
<div className="StockPrice">{stockPrice}</div>
<div className="PriceChangeRate">{priceChageRate}%</div>
<div className="PriceChangeAmount">
<div className="changeDirection">{chageDirection}</div> {priceChageAmount}
</div>
<div className="StockPrice">{data.stockInfResponseDto.stck_prpr}</div>
<div className="PriceChangeRate">{data.stockInfResponseDto.prdy_vrss}</div>
<div className="PriceChangeAmount">{data.stockInfResponseDto.prdy_ctrt}</div>
<TransactionVolume>
<span>{volumeText}</span>
{data.stockInfResponseDto.acml_vol}
{transactionVolume}
</TransactionVolume>
<TransactionValue>
<span>{valueText}</span>
{data.stockInfResponseDto.acml_tr_pbmn}
{transactionValue}
</TransactionValue>
</Container>
);
Expand All @@ -48,7 +62,7 @@ const StockOverview = () => {
export default StockOverview;

// component 생성
const Container = styled.div`
const Container = styled.div<{ priceChangeRate: number }>`
flex: 7 0 0;
overflow-x: scroll;
Expand Down Expand Up @@ -85,14 +99,25 @@ const Container = styled.div`
.StockPrice {
font-size: 18px;
color: #ed2926;
color: ${(props) => (props.priceChangeRate > 0 ? "#ed2926" : "#3177d7")};
font-weight: 530;
}
.PriceChangeRate,
.PriceChangeAmount {
font-size: 14px;
color: #ed2926;
color: ${(props) => (props.priceChangeRate > 0 ? "#ed2926" : "#3177d7")};
display: flex;
flex-direction: row;
gap: 2px;
.changeDirection {
font-size: 8px;
display: flex;
justify-content: center;
align-items: center;
}
}
`;

Expand Down
7 changes: 3 additions & 4 deletions client/src/hooks/useGetStockChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,10 @@ export default useGetStockChart;

// y축 눈금 옵션 설정하는 함수
const calculateYAxisOptions = (data: StockProps[]) => {
const sampleData = data.filter((_, index) => index % 10 === 0);
const samplePrice = sampleData.map((stock) => parseFloat(stock.stck_prpr));
const stockPrice = data.map((stock) => parseFloat(stock.stck_prpr));

const maxPrice = Math.max(...samplePrice);
const minPrice = Math.min(...samplePrice);
const maxPrice = Math.max(...stockPrice);
const minPrice = Math.min(...stockPrice);

const interval = Math.ceil((maxPrice - minPrice) / 10);
const min = Math.floor(minPrice - interval * 5);
Expand Down
39 changes: 38 additions & 1 deletion client/src/hooks/useGetStockInfo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,45 @@
import { useState, useEffect } from "react";
import { useQuery } from "react-query";
import axios from "axios";

const useGetStockInfo = (companyId: number) => {
const { data, isLoading, error } = useQuery(`stockInfo${companyId}`, () => getStockInfo(companyId), {});
const [autoRefetch, setAutoRefetch] = useState(false);

// 30분 or 정각여부 체크 함수 -> 30분 혹은 정각일 경우 api 1회 수동 요청 + 자동 요청 기능 활성화
const checkTime = () => {
const currentTime = new Date();
const minute = currentTime.getMinutes();

if (minute === 0 || minute === 30) {
refetch();
setAutoRefetch(true);
}

return minute;
};

// 현재 시각이 30분, 정각이 아닌 경우 남은 시간 계산하여 checkTime 함수 다시 실행
useEffect(() => {
const checkMinute = checkTime();

if (0 < checkMinute && checkMinute < 30) {
const delayTime = (30 - checkMinute) * 60000;
setTimeout(checkTime, delayTime);
}
if (30 < checkMinute && checkMinute < 60) {
const delayTime = (60 - checkMinute) * 60000;
setTimeout(checkTime, delayTime);
}
}, []);

const { data, isLoading, error, refetch } = useQuery(`stockInfo${companyId}`, () => getStockInfo(companyId), {
enabled: true,
refetchInterval: autoRefetch && 60000 * 10, // 정각 혹은 30분에 맞춰서 10분 마다 데이터 리패칭
refetchOnMount: true,
onSuccess: () => {
console.log(data);
},
});

return { data, isLoading, error };
};
Expand Down

0 comments on commit a2a6cb7

Please sign in to comment.