Skip to content
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

React Native: Decorators may get applied multiple times #185

Closed
thani-sh opened this issue Aug 4, 2017 · 24 comments
Closed

React Native: Decorators may get applied multiple times #185

thani-sh opened this issue Aug 4, 2017 · 24 comments

Comments

@thani-sh
Copy link
Contributor

thani-sh commented Aug 4, 2017

Moved issue: storybook-eol/react-native-storybook#50 (comment)

Hi @macrozone
Shall we continue discussing the issue here. Thanks

@macrozone
Copy link
Contributor

Any idea about this issue? or a proper way how to do react-native-storybook with hot reload properly?

@stale
Copy link

stale bot commented Dec 23, 2017

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 60 days. Thanks!

@stale
Copy link

stale bot commented Jan 7, 2018

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

@stale stale bot closed this as completed Jan 7, 2018
@sammiepls
Copy link

Am facing this issue when using global decorators for React Native storybook. Seems to be okay when I add a decorator to each story individually though, only gets affected by hot reload when it's a global decorator.
On version 5.3.25.

@shilman shilman transferred this issue from storybookjs/storybook Jun 18, 2021
@dannyhw
Copy link
Member

dannyhw commented Jun 20, 2021

@sammiepls Thanks for reporting this, I'll keep it in mind. Likely a fix will be part of the 6.0 release I'll make sure to test this once I have an alpha ready.

@dannyhw dannyhw reopened this Jun 20, 2021
@luciddr34m3r
Copy link

I'm bumping into this issue when I attempt to decorate stories with the auth providers necessary to work with firebase/reactfire, regardless of hot reload status.

@dannyhw
Copy link
Member

dannyhw commented Sep 13, 2021

I'm bumping into this issue when I attempt to decorate stories with the auth providers necessary to work with firebase/reactfire, regardless of hot reload status.

@luciddr34m3r What version of storybook are you using? If you can provide a repo with a minimal reproduction that would be awesome for helping debug the issue.

@luciddr34m3r
Copy link

Here's all my storybook deps:

    "@storybook/addon-actions": "^6.3.8",
    "@storybook/addon-essentials": "^6.3.8",
    "@storybook/addon-links": "^6.3.8",
    "@storybook/node-logger": "^6.3.8",
    "@storybook/preset-create-react-app": "^3.2.0",
    "@storybook/react": "^6.3.8"

Unfortunately the project is in a private repo but I can provide some snippets.

The decorator looks like this:

// preview.js

export const decorators = [
  (Story) => (
    <ThemeProvider theme={mainTheme}>
      <Story />
    </ThemeProvider>
  ),
  (Story) => (
    <SnackbarProvider maxSnack={3}>
      <Story />
    </SnackbarProvider>
  ),
  (Story) => (
    <FirebaseAppProvider firebaseConfig={firebaseConfig}>
      <Story />
    </FirebaseAppProvider>
  ),
];

The FirebaseAppProvider initializes a connection to firebase, but if the project has already been initialized, it will throw an error, so if I flip between stories, it seems to wrap the new story in a new decorator which re-initializes the database connection and pitches an error.

Pretty much the best I can do for now but I think the code will be public in awhile.

@dannyhw
Copy link
Member

dannyhw commented Sep 13, 2021

@luciddr34m3r this is the react-native repo, you might need to post an issue on the main repo https://github.com/storybookjs/storybook/issues

@luciddr34m3r
Copy link

Derp. Seemed nearly identical to the linked thread.

Thanks.

@dannyhw
Copy link
Member

dannyhw commented Sep 14, 2021

Derp. Seemed nearly identical to the linked thread.

Thanks.

@luciddr34m3r no problem it's an easy mistake to make :)

@thomasttvo
Copy link

thomasttvo commented Nov 24, 2021

Still happening on @storybook/react-native: 5.3.25

Apparently this only happens when all these happen at the same time:

  • You have global decorators
  • You have fast refreshes triggered by editing a story file

Example decorators where this issue can be seen:

addDecorator((getStory, context) => {
   return <View style={{ padding: 20, flex: 1 }}>{getStory(context)}</View>;
})
addDecorator(withBackgrounds) // @storybook/addon-ondevice-backgrounds

SOLUTION

Here's what I have done to fix the issue on my project:

Create these functions (I'm using Typescript here):

import { isValidElement, ReactElement, Fragment } from 'react';
import { DecoratorFunction } from '@storybook/addons';
import { addDecorator } from '@storybook/react-native';

const isReactElement = (value: unknown): value is ReactElement => {
  if (typeof value !== 'object') return false;
  return isValidElement(value);
};

const WRAPPER_ID = '__fast-refresh-fix';

const preventRedecorationAfterFastRefresh = (
  decorator: DecoratorFunction<unknown>,
): DecoratorFunction<unknown> => {
  return (getStory, context) => {
    const story = getStory(context);
    // check if the story has already run through the decorators before the fast refresh
    // if yes, don't decorate the story and return the old story element 
    if (isReactElement(story) && story.key === WRAPPER_ID) return story;
    return decorator(getStory, context);
  };
};

preventRedecorationAfterFastRefresh.decorator = ((getStory, context) => {
  const story = getStory(context);
  if (!isReactElement(story)) return story;
  // This acts as a flag to tell us whether the story has already run through the decorators 
  return (
    <Fragment key={WRAPPER_ID} >
      {story}
    </Fragment>
  );
}) as DecoratorFunction<unknown>;

Apply them like below

// Note that these are GLOBAL decorators
addDecorator(preventRedecorationAfterFastRefresh(decoratorA));
addDecorator(preventRedecorationAfterFastRefresh(decoratorB));
addDecorator(preventRedecorationAfterFastRefresh(decoratorC));
// this has to be the last call in the chain
addDecorator(preventRedecorationAfterFastRefresh.decorator);

@Aksana-Tsishchanka
Copy link

It seems it was added in v60 of react native storybook

@dannyhw
Copy link
Member

dannyhw commented Nov 16, 2022

in the latest v6 beta you can add this to Storybook.tsx at the top of the file as a workaround. You get a warning though.

import { clearDecorators } from "@storybook/react-native";
clearDecorators(); 

I'm looking for a better solution still.

@dannyhw
Copy link
Member

dannyhw commented Mar 4, 2023

Added a workaround in the storybook.requires file generation so I think this is at least partially solved.

@maharjanrajans
Copy link

@dannyhw Should clearDecorators() be removed to be used with Storybook 7.* versions?

@dannyhw
Copy link
Member

dannyhw commented Apr 22, 2023

@maharjanrajans v6 isn't compatible with v7 so im not sure what the question refers to

@maharjanrajans
Copy link

@dannyhw yeah, I mean are we planning to upgrade project to V7 to get rid of this warning.

WARN clearDecorators is deprecated and will be removed in Storybook 7.0.

As, this doesn't do trick to hide the logs

 if (__DEV__) {
    // stops the warning from showing on every HMR
    require("react-native").LogBox.ignoreLogs([
      "`clearDecorators` is deprecated and will be removed in Storybook 7.0",
    ]);
  }

@dannyhw
Copy link
Member

dannyhw commented Apr 24, 2023

V7 is planned but that will require changes to the integration with storybook core apis and v6 is still stabilising.

Since the warning comes from storybook core apis so it can't be removed easily before v7.

Also you can ignore the warning since it doesn't effect anything.

@hayata-suenaga
Copy link

Hello 👋 Is the team still planning to migrate to V7?

@dannyhw
Copy link
Member

dannyhw commented Oct 14, 2023

@hayata-suenaga yes there are already prs in progress for this

@nazmeln
Copy link

nazmeln commented Oct 18, 2023

Hi @dannyhw,
Do you know by any chance why LogBox is not muting a warning about decorators?
"react-native": "0.72.5",

@dannyhw
Copy link
Member

dannyhw commented Oct 22, 2023

logbox doesn't remove logs from metro just stops the logbox ui from showing on the device

@dannyhw
Copy link
Member

dannyhw commented Mar 7, 2024

should be resolved in latest versions

@dannyhw dannyhw closed this as completed Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants