위 그림처럼 내비게이션 바에 특정 티커를 입력하면 여러 컴포넌트와 함께 차트가 생성되는데
이 상태에서 다른 티커를 입력하면 아래와 같은 에러가 발생한다.
Maximum call stack size exceeded 에러는 무한 재귀 호출이나 이벤트 리스너, watcher가 너무 많이 호출될 때 발생할 수 있다고 한다.
<template>
<div class="discuss-count">
<div class="title">
<span v-if="stockData">{{ stockData.stockSymbol }} </span>
<span v-else>StockBurning </span>
<span>커뮤니티 의견 수 변화(1일 단위)</span><br>
</div>
<div class="chart" v-if="weeklyPostCountData">
<canvas ref="discussChart"></canvas> <!-- 차트를 렌더링할 캔버스 -->
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import Chart from "chart.js/auto";
export default {
name: 'DiscussCount',
data() {
return {
chart: null,
};
},
computed: {
...mapGetters(["stockData", "weeklyPostCountData"]), // Vuex에서 데이터 가져오기
},
watch: {
weeklyPostCountData: {
handler(newData) {
if (this.chart) { //기존 차트가 있으면
this.updateChart(newData);
} else { //기존 차트가 없으면
this.renderChart(newData);
}
},
deep: true, //객체 내부 변경을 감지함
},
},
mounted() {
this.watchTicker();
},
methods: {
watchTicker() {
this.$watch(
() => this.$route.query.ticker, // 감시할 대상
(newTicker) => {
if (newTicker) {
if (!this.weeklyPostCountData) {
this.$store.dispatch('fetchStockInfo', newTicker);
}
}
},
{ immediate: true } // mounted 시 즉시 실행
);
},
extractChartData(data) {
const labels = data.map(entry => entry.date);
const counts = data.map(entry => entry.count || 0);
const bullishCounts = data.map(entry => entry.bullishCnt || 0);
const bearishCounts = data.map(entry => entry.bearishCnt || 0);
return { labels, counts, bullishCounts, bearishCounts };
},
renderChart(data) {
if (!this.$refs.discussChart || !data) return;
const ctx = this.$refs.discussChart.getContext("2d");
const { labels, counts, bullishCounts, bearishCounts } = this.extractChartData(data);
this.chart = new Chart(ctx, {
type: "line",
data: {
labels: labels,
datasets: [
{
label: "게시글 수",
data: counts,
borderColor: "rgba(75, 192, 192, 1)",
backgroundColor: "rgba(75, 192, 192, 0.2)",
borderWidth: 3,
fill: true,
},
{
label: "상승 의견 수",
data: bullishCounts,
borderColor: "rgba(54, 162, 235, 1)",
backgroundColor: "rgba(54, 162, 235, 0.2)",
borderWidth: 3,
fill: true,
},
{
label: "하락 의견 수",
data: bearishCounts,
borderColor: "rgba(255, 99, 132, 1)",
backgroundColor: "rgba(255, 99, 132, 0.2)",
borderWidth: 3,
fill: true,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
labels: {
usePointStyle: true,
boxWidth: 7,
boxHeight: 7,
font: {
size: 14, // 라벨 폰트 크기
family: "'Arial', sans-serif", // 폰트 종류
},
color: '#ffffff',
},
},
},
scales: {
x: {
ticks: {
color: "#d4d2d2",
font: {
weight: "bold",
},
}
},
y: {
ticks: {
color: "#d4d2d2",
font: {
weight: "bold", // X축 라벨 폰트 굵기 (bold)
},
},
beginAtZero: true,
},
},
},
});
},
updateChart(newData) {
if (!this.chart) {
console.log(1);
return;
}
const { labels, counts, bullishCounts, bearishCounts } = this.extractChartData(newData);
console.log(2);
this.chart.data.labels = labels;
this.chart.data.datasets[0].data = counts;
this.chart.data.datasets[1].data = bullishCounts;
this.chart.data.datasets[2].data = bearishCounts;
console.log(3);
this.chart.update();
console.log(4);
},
},
};
</script>
다음 코드에서 console.log(숫자) 를 통해 에러가 발생하는 부분을 확인한 결과
this.chart.update(); 에서 에러가 발생하는 것을 확인하였고
updateChart(newData) {
if (!this.chart) {
console.log(1);
return;
}
this.chart.destroy();
const { labels, counts, bullishCounts, bearishCounts } = this.extractChartData(newData);
console.log(2);
this.chart.data.labels = labels;
this.chart.data.datasets[0].data = counts;
this.chart.data.datasets[1].data = bullishCounts;
this.chart.data.datasets[2].data = bearishCounts;
console.log(3);
this.renderChart(newData);
console.log(4);
},
this.chart.destroy();
this.renderChart(newData); 로 수정한 결과 제대로 차트가 렌더링되는 것을 확인할 수 있었다.
▶수정한 결과
'Vue' 카테고리의 다른 글
Vue 프로젝트 생성하기 (0) | 2025.05.06 |
---|---|
[문제 해결] 글을 작성하는 컨테이너에 긴 글을 쓰면 줄바꿈되지 않는 문제 (0) | 2025.02.27 |
[문제 해결] 게시글이 보였다가 다시 사라지는 문제 (0) | 2025.02.19 |
[문제 해결]자식 요소에 flex 비율을 지정해도 부모 요소의 100% 채워지지 않는 문제 (1) | 2025.02.03 |