Search code examples
vue.jsvuejs3vue-cli

Vue 3 (CLI): Cannot read properties of undefined (reading 'get')


When switching to Vue 3 CLI and consequently refactoring the code, this.$http.get('/api/todo/') no longer works. Instead of being returned a list of todos from the database, I receive a Cannot read properties of undefined error in the console:

app.js:209 Uncaught TypeError: Cannot read properties of undefined (reading 'get')
    at Proxy.getTodos (Todos.vue?4897:38:1)
    at Proxy.mounted (Todos.vue?4897:28:1)
    at eval (runtime-core.esm-bundler.js?d2dd:2722:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:164:1)
    at hook.__weh.hook.__weh (runtime-core.esm-bundler.js?d2dd:2697:1)
    at flushPostFlushCbs (runtime-core.esm-bundler.js?d2dd:341:1)
    at render (runtime-core.esm-bundler.js?d2dd:6247:1)
    at mount (runtime-core.esm-bundler.js?d2dd:4440:1)
    at app.mount (runtime-dom.esm-bundler.js?2725:1574:1)

Additionally, I observe that both the apps and components lists are empty in Vue devtools.

After searching and experimenting with solutions for a few hours, I have not found a solution that works yet.

This is the current code causing the issues:

In Todos.vue, the template is rendered because I do se "Hi there", but I do not see any list items anymore:

<template>
    <div id="TODOS">
      Hi there
      <ol>
        <li v-for="todo in v_todos" :key="todo.id">
          <span style="color:red;">{{ todo.name }}</span>
        </li>
      </ol>
    </div>
  </template>
  
  <script>
  export default {
    // el: "#TODOS",
    name: 'Todos',
    
    data() {
      return {
        v_todos: [],
      }
    },
  
    computed: {},
    components: {},
  
    mounted() {
        this.getTodos();
    },
  
    methods: {
          getTodos: function () {
              this.$http.get('/api/todo/')
                  .then((response) => { 
                    this.v_todos = response.data; 
                })
                  .catch((err) => { 
                    console.log(err); 
                })
          },
  }
  </script>

In App.vue:

<template>
    <div id="App">
      <Todos />
    </div>
    
  </template>
  
  <script>
  import Todos from './components/Todos.vue'
  
  export default {
    name: 'App',
    components: {
      Todos
    }
  }
  </script>

In the HTML page todos.html:

...
<div id="App"></div>
...

In base.html, at the end of the body:

  <script type="text/javascript" src="{% static 'src/vue/dist/js/chunk-vendors.js' %}"></script>
  <script type="text/javascript" src="{% static 'src/vue/dist/js/app.js' %}"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

I am completely new to Vue, so I would strongly appreciate if solution proposals are presented in a simple-to-understand way.


Solution

  • add to your main.js

    import axios from 'axios';
    
    const app = createApp(App);
    
    app.config.globalProperties.$http = axios;