Search code examples
vue.jsstorequasar-framework

[Vue warn]: Maximum recursive updates exceeded


I get the following warning which causes that when I open this route the component takes a while to load and then the menu remains bugged. [Vue warn]: Maximum recursive updates exceeded. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function. What I suspect is that it may be because we store the data in a store variable:

Here is the front-end code in which I call the store and paint a rangeBar graph:

<template>
    <q-page>
      <div class="q-pa-md">
        <VueApexCharts
          v-if="!adquisicionStore.loading"
          type="rangeBar"
          height="200" 
          :options="chartOptions" 
          :series="chartSeries"
        />
      </div>
    </q-page>
 </template>

<script setup>
  import VueApexCharts from "vue3-apexcharts";
  import { useAdquisicion } from "../stores/main";
  import { ref, onMounted } from "vue";
  
  const adquisicionStore = useAdquisicion();
  
  const chartSeries = ref([
    {
      name: 'horno1',
      data: [],
    }
  ]);
  
  const chartOptions = {
    plotOptions: {
      bar: {
        horizontal: true,
        barHeight: '20%'
      }
    },
    xaxis: {
      type: 'datetime'
    },
    stroke: {
      width: 1
    },
    fill: {
      type: 'solid',
      opacity: 0.6
    },
    legend: {
      position: 'top',
      horizontalAlign: 'left'
    }
  };  
  
  onMounted(async () => {
    await adquisicionStore.loadHornoMarcha();
    updateChartSeries();
  });
  
  const updateChartSeries = () => {
    // Make sure adquisicionStore.hornoMarcha is an array of data
    chartSeries.value[0].data = adquisicionStore.hornoMarcha;
  }
  </script>

And this is the store:

import { defineStore } from 'pinia';
import axios from 'axios';

export const useAdquisicion = defineStore('adquisicion', {
  state: () => ({
    hornoMarcha: [],
    loading: true
  }),

  actions: {

      async loadHornoMarcha() {
        try {
          const responseHorMar = await axios.get('http://localhost:3000/horno-marcha');
          if (responseHorMar.status === 200) {
            this.hornoMarcha = responseHorMar.data;
            this.loading = false;
          } else {
            console.error('Error al obtener datos: Respuesta no válida');
          }
        } catch (error) {
          console.error('Error al obtener datos:', error);
        }
      },

  },
  
});

I was hoping that the page would load quickly and when opening the menu it wouldn't crash.


Solution

  • The problem comes from the apexcharts plugin and how it treats arrays. The solution was to put toRaw in :series. To remove reactivity.

    <template>
      <q-page>
        <div class="q-pa-md">
          <VueApexCharts
            type="rangeBar"
            :height="200"
            :options="chartOptions"
            :series="toRaw(chartSeries)"
          />
        </div>
      </q-page>
    </template>
    
    <script setup>
    import VueApexCharts from 'vue3-apexcharts';
    import { useAdquisicion } from "../stores/example-store";
    import { ref, onMounted, toRaw } from "vue";
    
    const adquisicionStore = useAdquisicion();
    
    const chartSeries = ref([]); // Ahora es un array vacío para los datos
    
    const chartOptions = {
        plotOptions: {
          bar: {
            horizontal: true,
            barHeight: '20%'
          }
        },
        xaxis: {
          type: 'datetime'
        },
        stroke: {
          width: 1
        },
        fill: {
          type: 'solid',
          opacity: 0.6
        },
        legend: {
          position: 'top',
          horizontalAlign: 'left'
        }
      };
    
    const fetchHornoMarcha = async () => {
      try {
        const response = await adquisicionStore.loadHornoMarcha();
        console.log
        // Asigna los datos a chartSeries
        chartSeries.value = [{
          data: response
        }];
      } catch (error) {
        console.error("Error al cargar datos:", error);
      }
    };
    
    onMounted(async () => {
      await fetchHornoMarcha();
    });
    
    </script>
    
    <style scoped>
    #time-chart {
      width: 100%;
    }
    </style>