-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Since v4.0.2 getting error "Storybook preview hooks can only be called inside decorators and story functions." #282
Comments
If I understand #279 correctly this change was necessary to be compatible with // .storybook/preview.tsx
const Container = (props: DocsContainerProps) => (
<DocsContainer
{...props}
theme={{
...common,
...(useDarkMode() ? themes.dark : themes.light), // <<<
}}
/>
); Unfortunately, this broke with https://github.com/grubersjoe/react-activity-calendar/blob/main/.storybook/preview.tsx I don't know why Storybook did these changes but they feel quite limiting =/. |
Found workaround for dark mode const preview: Preview = {
docs: {
container: (props: {
children: React.ReactNode;
context: DocsContextProps;
theme?: ThemeVars;
}) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [isDark, setDark] = React.useState(true);
props.context.channel.on(DARK_MODE_EVENT_NAME, (state) =>
setDark(state)
);
const currentProps = { ...props };
currentProps.theme = isDark ? themes.dark : themes.light;
return <DocsContainer {...currentProps} />;
},
} |
More a bit cleaner pragmatic solution const MyDocsContainer = (props: {
children: React.ReactNode;
context: DocsContextProps;
theme?: ThemeVars;
}) => {
const [isDark, setDark] = React.useState(true);
React.useEffect(() => {
props.context.channel.on(DARK_MODE_EVENT_NAME, setDark);
return () =>
props.context.channel.removeListener(DARK_MODE_EVENT_NAME, setDark);
}, [props.context.channel]);
return (
<DocsContainer
{...props}
theme={isDark ? themes.dark : themes.light}
/>
);
} |
I mean it's a hack, but that's a lot better than what I came up with spontaneously :D. Thanks for sharing! |
How do we access the current color mode in a single story? |
@skaneprime Although this solution works. However, it creates some flickering when switching between docs. |
Is there maybe a way to cache the current value and use it instead of a hardcoded |
By using the channel from preview you can make a hook which can be used in both docs container and decorator import { addons } from '@storybook/preview-api';
const channel = addons.getChannel();
function useDarkMode() {
const [isDark, setDark] = React.useState(false);
React.useEffect(() => {
channel.on(DARK_MODE_EVENT_NAME, setDark);
return () => channel.off(DARK_MODE_EVENT_NAME, setDark);
}, [channel, setDark]);
return isDark;
} Based off this section of the readme |
Based on your suggestions, to avoid the initial blinking when switching to dark mode or reloading a page already in dark mode, you can store the setting in const [isDark, setDark] = useState(isDarkModeEnabled());
useEffect(() => {
channel.on(DARK_MODE_EVENT_NAME, state => {
setDarkModeEnabled(state);
setDark(state);
});
return () => channel.removeListener(DARK_MODE_EVENT_NAME, setDark);
}, []);
// ...
const LOCAL_STORAGE_KEY = '_tmp-dark-mode-hack';
export const isDarkModeEnabled = () => Boolean(localStorage.getItem(LOCAL_STORAGE_KEY));
export const setDarkModeEnabled = (enabled: boolean) =>
enabled
? localStorage.setItem(LOCAL_STORAGE_KEY, '1')
: localStorage.removeItem(LOCAL_STORAGE_KEY); |
Summary
After upgrading to version 4.0.2 I am getting the error
Storybook preview hooks can only be called inside decorators and story functions.
Downgrading to 4.0.1 makes the error goes away.
This is likely related to the changes in #279
Is there something I need to change on my end?
Full error
Reference
My storybook
.storybook/preview.tsx
for reference:Versions
storybook: 8.1.10
storybook-dark-mode: 4.0.2
The text was updated successfully, but these errors were encountered: