quasarframework / quasar

Quasar Framework - Build high-performance VueJS user interfaces in record time
https://quasar.dev
MIT License
25.97k stars 3.53k forks source link

Warning `[Vue warn]: Invalid VNode type: undefined (undefined)` in `QTable`. #12486

Closed maarteNNNN closed 2 years ago

maarteNNNN commented 2 years ago

What happened?

I tried making a Codepen with an example however it's only happening in the Quasar CLI . I'm getting recursive errors of Vue warn]: Invalid VNode type: undefined (undefined) on both examples (one is commented). Until finally the a warning pops:

runtime-core.esm-bundler.js?9e79:38 [Vue warn]: Maximum recursive updates exceeded in component <QTable>. 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.

NOTE: This is done with the Quasar CLI with Typescript. I tried to minimize the problem. The template is an exact copy of Selection cell slots. I tried this in a bare minimum project with Typescript.

EDIT: Seems I could make it so the Codepen is acting weird as well. However it's not showing the same warnings... It simply loads sometimes, other times it doesn't.

<template>
  <div class="q-pa-md">
    <q-table
      title="Treats"
      :rows="orders"
      :columns="columns"
      row-key="name"
      selection="multiple"
      v-model:selected="selected"
    >
      <template v-slot:header-selection="scope">
        <q-toggle v-model="scope.selected" />
      </template>

      <template v-slot:body-selection="scope">
        <q-toggle v-model="scope.selected" />
      </template>
    </q-table>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';

const columns = [
  { name: 'description', label: 'description', field: 'description' },
  { name: 'class', label: 'class', field: 'class' },
  { name: 'creator', label: 'creator', field: 'creator' },
  { name: 'products', label: 'products', field: 'products' },
];

const sampleData = [
  {
    id: '09ccb006-5ded-445e-91e0-90611694390e',
    description: 'Practical Soft Gloves',
    creator: 'Daryl Hoppe',
    class: '1RVM4',
    products: [
      {
        id: '48d84225-c0b4-4256-8b36-4d5ea0c3f89b',
        url: 'http://amie.biz',
        unit: 'liter',
        product: 'Gorgeous Fresh Bacon',
        createdAt: '2022-02-14T14:28:26.705478+01:00',
        deletedAt: null,
      },
    ],
  },
  {
    id: '10a3dfea-b4de-414b-b295-82d4337c5e62',
    description: 'Awesome Rubber Bike',
    creator: 'Esteban Haley',
    class: '1RVM4',
    products: [
      {
        id: 'c31c83ff-6eae-4103-9dc3-7a0cc4bc3dce',
        url: 'http://hal.org',
        unit: 'gram',
        product: 'Rustic Metal Salad',
        createdAt: '2022-02-14T14:28:26.705478+01:00',
        deletedAt: null,
      },
    ],
  },
  {
    id: '24ea3c46-da32-400a-bd39-a30b38c2f97f',
    description: 'Intelligent Frozen Tuna',
    creator: 'Marc Franecki',
    class: '1RVM4',
    products: [
      {
        id: '48d84225-c0b4-4256-8b36-4d5ea0c3f89b',
        url: 'http://amie.biz',
        unit: 'liter',
        product: 'Gorgeous Fresh Bacon',
        createdAt: '2022-02-14T14:28:26.705478+01:00',
        deletedAt: null,
      },
    ],
  },
];

const selected = ref([]);

const orders = ref([]);

onMounted(
  async () =>
    (orders.value = await new Promise((res) =>
      setTimeout(() => res(sampleData), 100)
    ))
);
</script>

What did you expect to happen?

To load the app without the warning.

Reproduction URL

https://codepen.io/maarteNNNN/pen/podWPNW?editors=101

How to reproduce?

$ quasar create bugreport                                                                                                                                                                                                                                                            Mon 14 Feb 2022 10:20:11 PM -03

  ___                             
 / _ \ _   _  __ _ ___  __ _ _ __ 
| | | | | | |/ _` / __|/ _` | '__|
| |_| | |_| | (_| \__ \ (_| | |   
 \__\_\\__,_|\__,_|___/\__,_|_|   

? Target directory exists. Continue? Yes
? Project name (internal usage for dev) bugreport
? Project product name (must start with letter if building mobile apps) Quasar App
? Project description A Quasar Framework app
? Author
? Pick your CSS preprocessor: SCSS
? Check the features needed for your project: ESLint (recommended), TypeScript, Vue-i18n
? Pick a component style: Composition
? Pick an ESLint preset: Prettier

Then just copy paste the example in Index.vue

Flavour

Quasar CLI (@quasar/cli | @quasar/app)

Areas

Components (quasar)

Platforms/Browsers

Chrome

Quasar info output

Operating System - Linux(5.15.15-76051515-generic) - linux/x64
NodeJs - 14.17.4

Global packages
  NPM - 7.20.3
  yarn - 1.22.17
  @quasar/cli - 1.2.2
  @quasar/icongenie - Not installed
  cordova - Not installed

Important local packages
  quasar - 2.5.5 -- Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
  @quasar/app - 3.3.3 -- Quasar Framework local CLI
  @quasar/extras - 1.12.5 -- Quasar Framework fonts, icons and animations
  eslint-plugin-quasar - Not installed
  vue - 3.2.31 -- The progressive JavaScript framework for building modern web UI.
  vue-router - 4.0.12
  vuex - 4.0.2 -- state management for Vue.js
  electron - Not installed
  electron-packager - Not installed
  electron-builder - Not installed
  @babel/core - 7.17.2 -- Babel compiler core.
  webpack - 5.68.0 -- Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
  webpack-dev-server - 4.7.4 -- Serves a webpack app. Updates the browser on changes.
  workbox-webpack-plugin - Not installed
  register-service-worker - 1.7.2 -- Script for registering service worker, with hooks
  typescript - 4.5.5 -- TypeScript is a language for application scale JavaScript development
  @capacitor/core - Not installed
  @capacitor/cli - Not installed
  @capacitor/android - Not installed
  @capacitor/ios - Not installed

Quasar App Extensions
  *None installed*

Networking
  Host - pop-os
  eno2 - 192.168.0.95
  wlo1 - 192.168.0.73

Relevant log output

[Vue warn]: Invalid VNode type: undefined (undefined) 
  at <QTable title="Treats" rows= (3) [{…}, {…}, {…}] columns= (4) [{…}, {…}, {…}, {…}]  ... > 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy {__v_skip: true} > > 
  at <RouterView> 
  at <QPageContainer> 
  at <QLayout view="lHh Lpr lFf" > 
  at <MainLayout onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy {$i18n: {…}, $t: ƒ, …} > > 
  at <RouterView> 
  at <App>
[Vue warn]: Maximum recursive updates exceeded in component <QTable>. 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.


### Additional context

_No response_
github-actions[bot] commented 2 years ago

Hi @maarteNNNN! 👋

It looks like you provided an invalid or unsupported reproduction URL. Do not use any service other than Codepen, jsFiddle, Codesandbox, and GitHub. Make sure the URL you provided is correct and reachable. You can test it by visiting it in a private tab, another device, etc. Please edit your original post above and provide a valid reproduction URL as explained.

Without a proper reproduction, your issue will have to get closed.

Thank you for your collaboration. 👏

TonyMale commented 2 years ago

I have same problem with Quasar

TonyMale commented 2 years ago

I resolve this problem. Your property 'product' is Array. That call recursive update and crashes project in production. You can use function format in columns.

For example

const columns = [
  { name: 'description', label: 'description', field: 'description' },
  { name: 'class', label: 'class', field: 'class' },
  { name: 'creator', label: 'creator', field: 'creator' },
  { name: 'products', label: 'products', field: 'products', format: (val) => val.reduce((acc, curr) => acc + curr.product, '') },
];
petr-panek commented 2 years ago

I had a same problem. Thank you @TonyMale for solution.

syldman commented 2 years ago

another way is to use 'item' slot to override built-in rendering method