티스토리 뷰

 

vue3 환경에서 차트를 그리려고 한다. 기본적으로 chart.js를 사용하면서, vue3 기반으로 래핑해놓은 vue-chart-3를 활용하려고 한다. 그래서 공식문서 데모 페이지에 나와있는 대로 따라하려고 하니 문제가 하나 생겼다. 내가 화면에 보여줄 데이터는 백엔드와 비동기 통신을 통해서 받아야 한다. 그런데 데모 소스코드 상에서는 데이터가 아래와 같이 그냥 하드코딩 되어 있었다.

    // template
    <DoughnutChart :chartData="testData" />

    // script
    const dataValues = ref([30, 40, 60, 70, 5]);
    const dataLabels = ref(["Paris", "Nîmes", "Toulon", "Perpignan", "Autre"]);
    const testData =  {
      labels: dataLabels.value,
      datasets: [
        {
          data: dataValues.value,
        },
      ],
    };

실제 chart.js를 활용하는 사례에서는 데이터를 하드코딩해서 넣는 경우보단, 백엔드에서 데이터를 비동기로 받아온 후에 넣는 경우가 더 일반적이다. 하지만 chart.js는 차트를 그리는 데 필요한 데이터를 받으면 곧바로 canvas로 그려버리기 때문에, 그 이후에는 비동기로 데이터가 도착한다고 한들 차트가 변하지 않는다는 문제가 있다.
예를 들어 아래 코드와 같이 비동기 통신을 가장한 fetchData함수가 onMounted에서 실행된다 하더라도 차트는 그려지지 않는다.

    const dataValues = ref([]);
    const dataLabels = ref([]);

    onMounted(() => {
      fetchData().then((res) => {
        dataValues.value = res.map((item) => item.data);
        dataLabels.value = res.map((item) => item.label);
      });
    });

    const testData =  {
      labels: dataLabels.value,
      datasets: [
        {
          data: dataValues.value,
        },
      ],
    };

    const fetchData = () => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve([
              { data: 10, label: "a" },
              { data: 30, label: "b" },
              { data: 15, label: "c" },
              { data: 5, label: "d" },
              { data: 20, label: "e" },
            ]);
          }, 1000);
        });
      };

이를 해결하기 위해서는 dataValuesdataLabels의 반응성을 testData에 주입시켜주면 된다. 그래서 fetchData에서 1초 뒤에 값을 받아오고 나면 testData에서도 받아온 값으로 세팅되도록 해주면 된다. testData에 반응성을 부여하는 방법으로는 computed 또는 watch를 사용하면 되는데, computed를 사용하는 방법이 훨씬 간단하다.

    const testData = computed(() => {
      return {
        labels: dataLabels.value,
        datasets: [
          {
            data: dataValues.value,
          },
        ],
      };
    });

이런 식으로 computed로 감싸주면 1초 뒤에 차트가 그려지게 된다.

'Dev' 카테고리의 다른 글

vue3 modal transition(모달 트랜지션)  (0) 2023.03.09
vue3 route transition(라우트 트랜지션)  (0) 2023.03.09
vue 에서 스크롤 위치 저장  (0) 2023.03.09
프로젝트 회고  (0) 2023.02.18
vue 커스텀 디렉티브(custom directive)  (0) 2022.12.05
댓글