useAddonState: cannot read property 'getAddonState' of undefined
See original GitHub issueDescribe the bug I’m trying to create a custom addon to allow theme switching from an addon panel using Material UI. This means using state shared between the panel and ThemeProvider wrapped story.
When using the useAddonState
hook from ‘@storybook/api’, useAddonState
inside an index.js file for a custom addon produces the error Cannot read property ‘getAddonState’ of undefined. The hook works fine in the register.js file
To Reproduce Steps to reproduce the behavior:
- Follow the steps in Writing Addons up-to and including “Using the complex addon”
- run
yarn add @storybook/api -D
- Add the line
import { useAddonState } from '@storybook/api'
to the index.js file of the custom addon - Add the line
const [state, setState] = useAddonState('my/addon', 'test string')
into the wrapper function - Run storybook, inside the story area there should be the error “Cannot read property ‘getAddonState’ of undefined”
Expected behavior Nothing serious will happen because the state is not being used yet but storybook should not display any errors.
Screenshots
Code snippets register.js
import React from 'react'
import addons from '@storybook/addons'
import { useChannel } from '@storybook/api'
import { AddonPanel } from '@storybook/components'
import { STORY_RENDERED } from '@storybook/core-events'
const MyPanel = () => {
const emit = useChannel({
STORY_RENDERED: id => {
console.log('render')
},
'my/customEvent': pars => {
console.log('click', pars)
}
})
return <button onClick={() => emit('my/otherEvent')}>click to emit</button>
}
// Register the addon with a unique name.
addons.register('my/addon', api => {
// Also need to set a unique name to the panel.
addons.addPanel('my/addon/panel', {
title: 'My Addon',
render: ({ active, key }) => (
<AddonPanel key={key} active={active}>
<MyPanel />
</AddonPanel>
)
})
})
index.js
import React from 'react'
import addons, { makeDecorator } from '@storybook/addons'
import { useAddonState } from '@storybook/api'
import BrandProvider from '../../src/components/BrandProvider/BrandProvider'
export default makeDecorator({
name: 'withMyAddon',
parameterName: 'myParameter',
skipIfNoParametersOrOptions: false,
wrapper: (getStory, context, { parameters }) => {
const [state, setState] = useAddonState('my/addon', 'test string')
return <BrandProvider brand={'test'}>{getStory(context)}</BrandProvider>
}
})
System: Environment Info: System: OS: macOS Mojave 10.14.6 CPU: (12) x64 Intel® Core™ i7-8850H CPU @ 2.60GHz Binaries: Node: 11.13.0 - /usr/local/bin/node Yarn: 1.19.1 - /usr/local/bin/yarn npm: 6.11.3 - /usr/local/bin/npm Browsers: Chrome: 77.0.3865.120 Safari: 13.0.2 npmPackages: @storybook/addons: ^5.2.5 => 5.2.5 @storybook/api: ^5.2.5 => 5.2.5 @storybook/components: ^5.2.5 => 5.2.5 @storybook/core-events: ^5.2.5 => 5.2.5 @storybook/react: ^5.2.5 => 5.2.5
Issue Analytics
- State:
- Created 4 years ago
- Reactions:9
- Comments:10 (3 by maintainers)
In the latest alpha of 6.0 useAddonState should work in the preview when imported from
@storybook/client-api
https://github.com/storybookjs/storybook/blob/615ce7f097da7533c3390cc484ac9ff4f7ab1526/examples/dev-kits/stories/addon-useaddonstate.tsx#L3
Here’s the code that runs in the manager: https://github.com/storybookjs/storybook/blob/5e76eb71ca0d9e33bba0f73f2d3a33a56f5aeb7a/examples/dev-kits/manager.js#L23-L24
@Reignable can you share how you implemented state-sharing with
useChannel
?