Encountering an issue with Typescript Vue class-based components in Laravel Mix: issue arises when attempting to set property 'render' on an undefined object

I have been using Laravel Mix to compile my Vue components, incorporating TypeScript and class-based components. Each class is exported from the component, and every component is required by the context in the main application script. However, during rendering, Vue is throwing an error:

Uncaught TypeError: Cannot set property 'render' of undefined
    at normalizeComponent (componentNormalizer.js:24)

I've scoured the internet for solutions, but all I find are discussions about invalid export classes. I am confident that my classes are being exported correctly within the components. I'm not sure where I'm going wrong.

When I revert back to object-based components in plain JavaScript, everything works perfectly. This leads me to believe that there may be an issue with my TypeScript configuration. I feel completely defeated :(

app.ts

import Vue from 'vue';
import _ from "lodash"

export default class App {

    protected registerComponents(): void {
        const components = require.context('./', true, /\.vue$/i);

        components.keys().forEach((componentPath) => {
            // @ts-ignore
            const componentName = componentPath
                .split('/').pop() // full component name
                .split('.').slice(0, 1).shift(); // component name without extension

            Vue.component(
                _.kebabCase(componentName),
                components(componentPath)
            );
        })
    }

    protected boot(): void {
        this.registerComponents();
    }

    public init(): Vue {
        this.boot();

        return new Vue({
            el: '#main',
        });
    }
}

EventSignUpForm.vue

<template>
    <div>
        <p>Long-form v-model example</p>
    </div>
</template>

<script lang="ts">
    import Vue from 'vue'
    import {Component} from 'vue-property-decorator';

    @Component({
        name: 'EventSignUpForm',
    })
    export class EventSignUpForm extends Vue {

        protected count = 0

        public increment() {
            this.count++
        }

        public decrement() {
            this.count--
        }
    }

    export default EventSignUpForm;
</script>

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "moduleResolution": "node",
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "baseUrl": ".",
        "types": [
            "node",
            "webpack-env"
        ],
        "paths": {
            "@/*": ["./resources/js/*"]
        },
        "lib": [
            "esnext",
            "dom",
            "dom.iterable",
            "scripthost"
        ]
    },
    "include": [
        "resources/js/**/*.ts",
        "resources/js/**/*.tsx",
        "resources/js/**/*.vue"
    ],
    "exclude": [
        "node_modules"
    ]
}

webpack.mix.js

class WebpackMix {
    constructor() {
        this.mix = require('laravel-mix');
    }

    configureWebpack(){
        this.mix.webpackConfig({
            module: {
                rules: [
                    {
                        test: /\.tsx?$/,
                        loader: "ts-loader",
                        exclude: /node_modules/,
                    }
                ]
            },
            resolve: {
                extensions: ["*", ".js", ".jsx", ".vue", ".ts", ".tsx"],
                alias: {
                    '@': path.resolve(__dirname, 'resources', 'js'),
                },
            }
        });
    }
    // others things  
}

Answer №1

RegistrationForm.vue: Transform the component export to export default:

export class RegistrationForm extends Vue 

modify it to

export default class RegistrationForm extends Vue

and eliminate from the end

export default RegistrationForm;

Answer №2

With the assistance of my colleague, we were able to tackle a particularly challenging case.

To address the issue, we made modifications in the webpack.mix.js file within the ts-loader options object. Specifically, we included the TS suffix for Vue components as follows:

rules: [
  {
    test: /\.tsx?$/,
    loader: 'ts-loader',
    exclude: /node_modules/,
    options: {
      appendTsSuffixTo: [/\.vue$/]
    }
  }
]

Subsequently, we adjusted the compilerOptions.module in the tsconfig.js file from es2015 to commonjs:

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        // no changes to other settings
    }
}

An essential step involved modifying all imports/require statements for Vue components to default imports. Initially, I had used import in require.context, but it needed to be updated to the following format:

protected registerComponents(): void {
  const components = require.context('./', true, /\.vue$/i);

  components.keys().forEach((componentPath) => {
    // @ts-ignore
    const componentName = componentPath
      .split('/').pop() // complete component name
      .split('.').slice(0, 1).shift(); // component name without extension

    Vue.component(
      _.kebabCase(componentName),
      components(componentPath).default
    );
  })
}

This resolution successfully addressed my challenge, and I owe thanks to Adrian for his valuable input and effective solution :)

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

Add owl carousel to your npm project in any way you see fit

After struggling for a while, I finally wanted to implement owl-carousel, but couldn't figure out how to connect it using npm and webpack. The official NPM website states: Add jQuery via the "webpack.ProvidePlugin" to your webpack configuration: ...

What is the best way to save an object with methods in a Vue application?

Looking for the best way to store complex objects with methods in Vue? Take this object as an example: const behavior = { onClick() { console.log('click') }, onDoubleClick() { console.log('double click'); }, on ...

The @change event in Vue/Vuetify lacks certain properties in the $event object

Working on a project using Vuetify, I am implementing an edit-in-place feature. The transition between the span and text field is functioning properly, sending updates to the server as expected. One final task remains before considering this functionality ...

Non-reactive arrays in Vue.js

I am facing an issue. Here is the problem: data: { tracks: [] } The tracks array will contain a complex object. I want to achieve reactivity when assigning a new value to tracks nested object, but I do not need deep reactivity for the object. ...

Improved with TypeScript 4.1: Fixed-Size String Literal Type

The latest updates from the TypeScript team have shown significant improvements in string literal typing (4.1 & 4.2). I'm curious if there's a way to define a fixed length string. For example: type LambdaServicePrefix = 'my-application- ...

Having trouble editing a record in Vue.js/Vuetify/Axios after it has been created

After creating a new record, I encounter an issue where updates don't reflect in the database until I refresh the page. This behavior has left me puzzled about its cause. The sequence of events goes as follows: 1) New record creation --> data sen ...

What methods are available to rapidly test Firebase functions?

While working with Typescript on firebase functions, I have encountered challenges in testing and experimenting with the code. Despite using the Lint plugin to identify errors without running the code, I am struggling to run the code and view the output. ...

The 'type' property within the NGRX Effect is not present in the type Observable<any[]>

I am currently in the process of upgrading my Angular app from version 6 to version 7. Additionally, I am upgrading the TypeScript version from 2.7.2 to 3.1.6. The issue I'm encountering is that TypeScript is flagging an error stating that my ngrx ef ...

Struggling with eliminating spacing between v-text-field elements and labels in Vuetify

Struggling to reduce the vast gap between rows in my Vuetify project. I've attempted using CSS and Vuetify spacing options, but haven't had any luck. Desired layout: Current layout: <v-container> <v-row> <v-col cols=" ...

An error is triggered by the EyeDropper API stating that 'EyeDropper' has not been defined

I am trying to utilize EyeDropper for an eyedropper function in my project that uses Vue2 + Ts. Here is the code snippet: <div v-if="haveEyeDropper" @click="handleClickPick" > <i class="iconfont icon-xiguan"> ...

Properties of untyped objects in TypeScript are not defined

Here is the code snippet I've been working on: file.js const channel = {}, arr = [string,string,string]; for(let i = 0;i < arr.length;i++ ){ channel[arr[i]] = "Amo" //equal string value } I have an array that contains only string values, for ...

What is the best way to integrate Vuejs while maintaining the integrity of the HTML5 structure

According to the official Vuejs documentation, when it comes to the mounting point: The designated element only acts as a mounting point. Unlike in Vue 1.x, the mounted element will always be replaced with DOM generated by Vue. Therefore, it is advised ...

At this time, the feature allowing for the use of the experimental syntax 'classProperties' is not activated

During the process of setting up React in a Django project, I encountered this error message: ModuleBuildError in Module build failed (from ./node_modules/babel-loader/lib/index.js): SyntaxError: C:\Users\1Sun\Cebula3\ ...

Display a spinner (preloader/loading indicator) each time the page transitions and remove it once all assets have finished loading in Vue Gridsome

I've set up a preloader using Gridsome (Vue static site generator with Vue Router). In my index.html, I added a simple div that covers the entire page. Then, to hide the preloader once everything has loaded, I included this JS code in index.html: wind ...

Despite the unconsumedBufferLength being 0, DataReader.loadAsync is still being completed

Working on UWP WinRT, I'm dealing with JSON stream consumption using the following code: async function connect() { let stream: MSStream; return new CancellableContext<void>( async (context) => { stream ...

Sorry, there was an error with Vue-i18n: Unable to access the 'config' property because it is undefined

Let's start by examining what functions correctly in App.js import router from './routes.js'; import VueI18n from 'vue-i18n'; const messages = { en: { message: { hello: 'hello world' } } } // Create ...

What is the best way to change a timestamp into a date format using Angular?

I am struggling to convert a timestamp to the date format 'dd/MM/YYYY' but keep getting a different date format in the output. I am using syncfusion spreadsheet for this task. export-electronic.component.ts updatedata(){ this.dataApi.get ...

What is the best way to responsively center an after pseudo-element above its parent?

Looking to create a dynamic tooltip without any fixed widths or constraints on the parent element. The process seems simple enough, but I'm facing an issue with centering the after element due to an existing transform attribute of transform: translat ...

Does utilizing the i18n module solely for the purpose of translating route names seem excessive?

My coding habit is to write everything in English for easy understanding by developers, but I'm encountering a dilemma while using Nuxt. All the page components I create are named in English, whereas our user base speaks a different language. Should I ...

Connecting a Node server with Vue socket: A step-by-step guide

I'm currently using vue.js (Laravel) to connect to my chat node server. While the socket connection is working fine, I'm facing issues with emitting data with a function. var socket = io.connect('http://localhost:3000/api/message'); so ...