storybook
storybook copied to clipboard
Trigger Vue event with $event happen `method "toJSON" is not defined` by Addon Action
Describe the bug
When adding the $event
props for the event method of Vue component and trigger the event on Storybook button,
the Addon Action and Vue will happen the error message below:
[Vue warn]: Property or method "toJSON" is not defined on the instance but referenced during render
To Reproduce
- I create an application with the command:
npx vue create vue-cli-storybook
with vue-router, vuex and eslint. (@vue/cli 4.5.13) - I install the Storybook with the command:
npx sb init
- Then, I add the
$event
props ononClick
method on the example file./src/stories/Button.vue
like this:
methods: {
onClick($event) {
this.$emit('onClick', $event);
},
},
- run storybook
npm run storybook
and open Addon Actions console to trigger the button event.
The example repository: https://github.com/VisionYi/vue-cli-storybook
System
- System:
- OS: macOS 11.1
- CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
- Binaries:
- Node: 14.15.4 - /usr/local/bin/node
- Yarn: 1.22.10 - /usr/local/bin/yarn
- npm: 6.14.10 - /usr/local/bin/npm
- Browsers:
- Chrome: 90.0.4430.212
- Firefox: 85.0
- Safari: 14.0.2
- npmPackages:
- @storybook/addon-actions: ^6.2.9 => 6.2.9
- @storybook/addon-essentials: ^6.2.9 => 6.2.9
- @storybook/addon-links: ^6.2.9 => 6.2.9
- @storybook/vue: ^6.2.9 => 6.2.9
Additional context I think it is related to this issue [Addon Action in v5]: Issue when serializing a Vue instance.
In my real project with Storybook v6.1.x that didn't happen like this error, but I upgrade the version to v6.2.9 just have this problem...
In addition, this problem causes severe delay to trigger the event.
I had the same issue, but for me it is only present when I have v-on="$listeners"
on my component. Like this:
<template>
<button v-on="$listeners">
<slot />
</button>
</template>
Hi, @shilman Could the Storybook team fix this issue? or any plan to improve that?
@VisionYi does the workaround in #14933 work for you?
@shilman
I only can replace $event
with a clear value as a prop, it can avoid the error message that happened.
Avoid Vue event object as the prop to pass to the parent component.
But it is not a workaround.
By the way, https://github.com/storybookjs/storybook/issues/14933#issuecomment-862621433 is also not a workaround.
Hi,
I am also experiencing the above issue, the differences being that:
-
my package version are as follows:
"@storybook/addon-actions": "^6.3.0", "@storybook/addon-essentials": "^6.3.0", "@storybook/vue": "^6.3.0"
-
I am using the actions through the args property on the template:
Button.args = { onClick: action('clicked'), }
The result I see is:
- an immediate action is printed in the actions panel, containing the event that was emitted from the tested component and accompanied by the console message regarding the "toJSON" method
- then a pretty long pause where the browser is frozen
- and finally an additional action is displayed in the actions panel.
Please note that that last event contains eventPhase: 3, so I assume it is displayed as a result of the bubbling phase of the event.
Thanks!
I'm also experiencing this issue. I need my vue component to emit the native event because I'm going to be using it in a library. Is there a solution for this?
I think I figured it out to some extent, though with some limitations.
make sure to have this in your preview.js file
export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" },
This will cause storybook to automatically generate action objects for each action that the component dispatches, which matches the above matcher.
so this forced me to change the name of my event from "click" to "onClick", because otherwise it did not get picked up.
now my template in the story looks something like this:
template: '<Button :label="label" :size="size" :type="type" @onClick="onClick"/>',
and I don't define the onClick function anywhere in my file, it is created for me by storybook.
and now when I click my button, I don't get an error and only one action shows up in the actions tab.
I don't like that it forces me to change the event name, but I guess I can live with it, or take the time to play around with the regex.
I found the issue source:
- @storybook/addon-actions use the
Telejson
library to stringify the props ($event) of Vue event and show them on the Actions console. -
Telejson
stringify the props ($event) byJSON.stringify
and do some conversion processes to be an object (?) -
JSON.stringify
will call property namedtoJSON
. (reference link) - Vue will warn about an undeclared method being referenced during render.
[Vue warn]: Property or method "toJSON" is not defined on the instance but referenced during render
Then, I try below testing: (change $event
to this
)
// Button.vue
methods: {
onClick($event) {
this.$emit('onClick', this);
},
},
It also will get the same error warning. I think this issue is Telejson
caused a puzzling error in Vue.
The workaround is to insert the toJSON
method in the Vue instance or component instance, like:
// Button.stories.js
const Template = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { MyButton },
template: '<my-button @onClick="onClick" v-bind="$props" />',
methods: { toJSON: () => {} },
});
or Vue top-level prototype, you can put it on .stroybook/preview.js
file:
Vue.prototype.toJSON = () => {}
Actually, please put this solution on the Addon Actions Readme.md, because it is a special error case for Vue and depend on the Telejson
issue or technical limitations.
@metal-gogo @reutgrubervcita @LawrenceB5477 You can try the workaround above on your project.
Any updates on this issue?
Any updates on this issue?