Beta.5 Issue when unmounting component
Version
3.1.0-beta.5
Reproduction link
EDIT: https://github.com/AlexandreBonaventure/vue-beta-unmount-bug
I don't have a reproduction link because these kind of bugs are very difficult to isolate (I tried but failed to reproduce without exposing a lot of code). However, I can confirm this happened when we upgraded to beta-5 and not fixed following beta releases.
I've attached a video with the devtool to provide debugging info.
I'm willing to provide more information as necessary, and you guys can maybe help me figure things out as you have more insights on what's going on behind the scenes.
https://user-images.githubusercontent.com/4596409/120663906-7855ff00-c458-11eb-9972-b90f0cc818c5.mp4
Steps to reproduce
The bug happens when unmounting a component tree
What is expected?
Should work as expected
What is actually happening?
TypeError: Cannot read property 'type' of null at unmountComponent
- Are you using Suspense?
- Can you confirm that: (1) it works in beta.4, and (2) still broken in beta.7?
There are only 7 commits between beta.4 and beta.5 so if possible you can build and link @vue/runtime-core
locally to isolate the commit that caused the issue.
- Not using Suspense
- It works in 3.x including (beta.4) and still broken in beta.7, yup!
OK doing that now!
There are only 7 commits between beta.4 and beta.5 so if possible you can build and link @vue/runtime-core locally to isolate the commit that caused the issue.
So after investigation it turns out the culprit is this one commit: https://github.com/vuejs/vue-next/commit/201060717d4498b4b7933bf8a8513866ab9347e4
Maybe this can help too... Here's the source code for the component which instance is null:
<script lang="ts">
import { defineComponent, h, computed, mergeProps } from 'vue';
import UIButton from './UIButton.vue';
import UIIcon from './UIIcon.vue';
export const themes = [
'primary',
'error',
'warning',
];
const getProps = arr => arr.reduce((acc, theme) => ({
...acc,
[theme]: {
type: Boolean,
required: false,
},
}), {});
const ButtonOrSpan = (props, { attrs, slots }) => {
if (props.interactive) {
return h(UIButton, attrs, slots.default);
}
return h('span', mergeProps({ class: 'dib', style: { 'line-height': 1 } }, attrs), slots.default());
};
export default defineComponent({
components: {
UIIcon,
ButtonOrSpan,
},
props: {
...getProps(themes),
interactive: {
type: Boolean,
default: true,
},
icon: {
type: String,
},
},
emits: {
delete: null,
},
setup (props) {
const styleClasses = computed(() => {
const filterThemes = themes.filter((theme) => props[theme]);
if (!filterThemes.length) return ['primary'];
return filterThemes;
});
const themeStyleClass = computed(() => `-${styleClasses.value.join('-')}`);
return {
themeStyleClass,
};
},
});
</script>
<template>
<ButtonOrSpan
unstyled
:interactive="interactive"
class="ui-pill"
:class="[ $style[themeStyleClass], themeStyleClass, $style.pill ]"
>
<span class="dib">
<UIIcon
v-if="icon"
:name="icon"
class="icon dib v-mid mr1"
/>
<slot />
</span>
<UIIcon
v-if="interactive"
name="x"
class="icon dib v-mid ml1"
@click="$emit('delete')"
/>
</ButtonOrSpan>
</template>
I'll need a bit more context on how this component is used when it throws the error - i.e. the parent chain and how this component is consumed by its parent.
Still, it's going to be very difficult to identify the issue without actual runnable reproduction so I would still strongly encourage you to try to provide one (a big one is fine). If you worry about exposing code, you can use a private repo and invite me.
@yyx990803 phewww, this was not an easy task but I've managed to create a minimal repro!
https://github.com/AlexandreBonaventure/vue-beta-unmount-bug
after yarn && yarn dev
Click on the Toggle button.
The code is super contrived because I spend an hour trimming my app to get to the root of it. So now that all the code is trimmed it does not makes much sense anymore but I hope this will help you out