Encountering the issue of "Cannot read properties of undefined" while attempting to pass data to a prop

Currently, I am developing a Vue application that heavily relies on charts. The issue lies in the fact that I am fetching data from the database individually for each chart component, resulting in multiple calls and a slower page load time. I am looking to optimize this by fetching data from the database once and then passing it to each chart component via props. However, I have faced difficulties in implementing this approach.

Here is an example of the data structure:

https://i.sstatic.net/Lg4fk.png

In my main component, I retrieve data from another component that manages the API (called BIService). This main component also contains all the chart components.

<template>
        <b-row cols="1" cols-sm="2" cols-lg="4">
          <b-col class="mb-4">
            <total-empty-units />
          </b-col>
          <b-col class="mb-4">
            <vacancy-rent-loss />
          </b-col>
          <b-col class="mb-4">
            <churn-rate />
          </b-col>
          <b-col class="mb-4">
            <overdue-payments-chart />
          </b-col>
        </b-row>
</template>
        
<script>
  import axios from '@/config/axios';
  import {biService} from '@/services/bi';
  import TotalEmptyUnits from '@/components/chart/empty-units/TotalEmptyUnits';
  import OverduePaymentsChart from '@/components/chart/overdue-payments/OverduePaymentsChart';
  import ChurnRate from '@/components/chart/churn-rate/ChurnRate';
  import VacancyRentLoss from '@/components/chart/vacancy-loss/VacancyRentLoss';

  export default {
    components: {
      TotalEmptyUnits,
      OverduePaymentsChart,
      ChurnRate,
      VacancyRentLoss,
    },
    data: () => ({
      bIGraphStats: null,

    }),
    methods: {
      load() {
        biService.getBIGraphStatsForCompany()
            .then(result => this.bIGraphStats = result.data)
            .catch(error => console.error(error));
 
      },

    },
  };
</script>

As shown in the chart component example below, I am also making database calls within the individual chart components.

<template>
  <b-card class="h-100" @click="showModal = true">
    <div class="d-flex">
      <h5 class="text-center flex-grow-1">Churn rate</h5>
      <b-button variant="link" class="p-0">
        <i class="fas fa-external-link-square-alt fa-lg"></i>
      </b-button>
    </div>
    <apexchart
      type="radialBar"
      height="250"
      :chartData="chartData"
      :options="options"
      :series="series">
    </apexchart>
  </b-card>
</template>

With the new approach, I have added a prop to the chart component named seriesData and attempted to pass it to the main component where the database data is fetched using a watcher. However, I am encountering an error "Cannot read properties of undefined" when trying to pass the data.

Below is a snippet of the updated code structure:

The main component:

          <b-col class="mb-4">
            <churn-rate v-if="loaded" :series-data="bIGraphStats" />
          </b-col>

The chart component:

<template>
  <b-card class="h-100" @click="showModal = true">
    <div class="d-flex">
      <h5 class="text-center flex-grow-1">Churn rate</h5>
      <b-button variant="link" class="p-0">
        <i class="fas fa-external-link-square-alt fa-lg"></i>
      </b-button>
    </div>
    <apexchart
      type="radialBar"
      height="250"
      :chartData="chartData"
      :options="options"
      :series="series">
    </apexchart>
  </b-card>
</template>

Answer №1

Props are not dependent on asynchronous operations being completed before they are passed down; they are passed down immediately. Initially, when the component is created, the prop is null. This may cause issues if the child component attempts to use null as a valid object prematurely. It is recommended to delay rendering the child component until the initial data is fetched and the prop is no longer null:

<b-col class="mb-4">
  <churn-rate v-if="loaded && bIGraphStats" :series-data="bIGraphStats" />
</b-col>

Answer №2

Instead of constantly using watchers and pushing data every time it changes, consider utilizing a computed property for the series data variable. Computed properties offer caching capabilities, making it a more efficient option. For more information on computed properties versus watchers, check out the VueDocs.

This applies to the chart component.

computed: {
  series () {
    if (this.seriesData) {
      return this.seriesData
    }
    return []
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Assign the value from the list to a variable in order to execute an API call

Imagine a scenario where there's a button that displays a random joke based on a specific category. The categories are fetched using an API request from https://api.chucknorris.io/jokes/categories The jokes are generated from https://api.chucknorris. ...

Issues with Vuex store causing incorrect value retrieval

In troubleshooting this issue, I am encountering a problem. My request to the back end is to retrieve data for display on the front end. The data fetched from the backend consists of recipes stored in an array. Utilizing v-for, I iterate through the array ...

Sending data from jQuery modal to the final input field

In my latest project, I have developed a modal window that features a table with rows of input boxes and buttons: <table class="datatable tablesort selectable paginate full" width="100%"> <tbody> ...

Various conditional statements based on the dropdown menu choice

I currently have a basic dropdown menu on my webpage that enables users to switch between viewing Actual or Planned dates/times in a table (I am utilizing the controller as syntax): <select ng-model="trip.viewType"> <option value="actual"> ...

Adding space around a label in a React component with TypeScript

Here is the code snippet I am working with: const ParentComponent = () => { const name = "name1"; const type = "type1"; const label = `${name} ${type}`; //something to be done here to add some space // before the text return ( ...

Executing a function in Node-Express with a database connection at the beginning of the application

I am relatively new to Node.js and currently working on a Node.js - Express solution as a back-end for an AngularJS web application. My goal is to send an email when the MSSQL database query returns specific information. I have successfully implemented thi ...

When a user clicks on a React listItem, the information for that specific item is displayed using

As a beginner in the coding world, I am currently learning about React and JSON. My project involves working on three interconnected panels. Specifically, I aim to showcase checklist answers on the third panel. First Panel: Displaying: All the ESN ("46 ...

trouble with fetching data

Within my Backbone view, I have the following code snippet: var BookView = Backbone.View.extend({ initialize: function() { this.render(); }, render: function() { this.model.fetch({ success : function(model, resp, opt) { alert(this.$el. ...

What is the process for taking a website project running on localhost and converting it into an Android web application using HTML, CSS, and JavaScript

Looking for recommendations on how to create an Android web application using HTML, CSS, and JavaScript. Any suggestions? ...

Creating a Dynamic Input Validation Range with JQuery

Greetings and thank you for taking the time to review this! :-) The form validation is functioning correctly with required fields, but I am facing a challenge with setting up numeric range validation dynamically for an autocomplete feature. The JQuery val ...

Steps for generating random numbers from a set of given numbers

I am faced with a scenario where I need to generate random numbers based on a given set of numbers. For instance, if I have an array num=[23,56,12,22], I would like to obtain a random number from this array. ...

picking out a particular set of data from a JSON document

I have a map of Europe along with a JSON file that displays the unemployment rate for each country in the year 2011. The JSON file also includes x and y elements, allowing me to place a blue circle on top of each country on the map. My goal is to be able ...

What is the best way to fetch data for each specific ID using axios.post when making a URL call?

Utilizing Axios to fetch data from an API and display them as cards in a movie component, I am facing the challenge of enabling users to click on a single movie card and navigate to another page (singlepage.vue) with the corresponding movie ID from the API ...

What is the best way to change function.bind(this) to an arrow function in a react native application?

I am attempting to convert my function into an arrow function, but I keep encountering an error of undefined when passing props. <TextInput style={styles.input} value={formState.inputValues.title} onChangeText={textCh ...

Utilizing the invoke() method within the each() function in Cypress to access the href attribute

I recently started using Cypress and I'm attempting to retrieve the href attribute for each div tag within a group by utilizing invoke(), however, it is resulting in an error. Could anyone provide guidance on the correct way to achieve this? cy.get(&a ...

Error: the search variable is not defined

function sorting(type) { $("#parentDiv").empty(); $.getJSON("example_data.json", ({ Find })); function Locate(a, b) { return (a[Find.type] < b[Find.type]) ? -1 : (a[Find.type] > b[Find.type]) ? 1 : 0; }; } The example_data.j ...

Troubleshooting: Issue with detecting keypress using jQuery

Currently, I have a jQuery script that checks password strength and changes an image source based on complexity. The functionality works smoothly within jsFiddle (set to jQuery 1.91), but when implemented on my webpage, the event seems to not be triggered. ...

Fetching data from local JSON file is being initiated twice

I need some help understanding why my code is downloading two copies of a locally generated JSON file. Here is the code snippet in question: function downloadJson(data, name) { let dataStr = 'data:text/json;charset=utf-8,' + encodeURICompo ...

What is the process for sending JavaScript data to a Rails controller action?

Utilizing jQuery Shapeshift for drag and drop reordering of lists on my web application. I am looking to send the data below to my Rails controller action in order to update the list's order. Every time I drag a list, this is the output that appears ...

Handling errors within classes in JavaScript/TypeScript

Imagine having an interface structured as follows: class Something { constructor(things) { if (things) { doSomething(); } else return { errorCode: 1 } } } Does this code appear to be correct? When using TypeScript, I en ...