react-native icon indicating copy to clipboard operation
react-native copied to clipboard

React Native: Decorators may get applied multiple times

Open thani-sh opened this issue 6 years ago • 23 comments

Moved issue: https://github.com/storybook-eol/react-native-storybook/issues/50#issuecomment-320232611

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

thani-sh avatar Aug 04 '17 12:08 thani-sh

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

macrozone avatar Oct 03 '17 12:10 macrozone

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[bot] avatar Dec 23 '17 22:12 stale[bot]

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[bot] avatar Jan 07 '18 22:01 stale[bot]

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.

sammiepls avatar Jun 18 '21 01:06 sammiepls

@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 avatar Jun 20 '21 10:06 dannyhw

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 avatar Sep 13 '21 20:09 luciddr34m3r

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.

dannyhw avatar Sep 13 '21 22:09 dannyhw

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.

luciddr34m3r avatar Sep 13 '21 22:09 luciddr34m3r

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

dannyhw avatar Sep 13 '21 22:09 dannyhw

Derp. Seemed nearly identical to the linked thread.

Thanks.

luciddr34m3r avatar Sep 13 '21 22:09 luciddr34m3r

Derp. Seemed nearly identical to the linked thread.

Thanks.

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

dannyhw avatar Sep 14 '21 07:09 dannyhw

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);

thomasttvo avatar Nov 24 '21 17:11 thomasttvo

It seems it was added in v60 of react native storybook

Aksana-Tsishchanka avatar Oct 05 '22 22:10 Aksana-Tsishchanka

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 avatar Nov 16 '22 01:11 dannyhw

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

dannyhw avatar Mar 04 '23 13:03 dannyhw

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

maharjanrajans avatar Apr 21 '23 22:04 maharjanrajans

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

dannyhw avatar Apr 22 '23 06:04 dannyhw

@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",
    ]);
  }

maharjanrajans avatar Apr 24 '23 15:04 maharjanrajans

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.

dannyhw avatar Apr 24 '23 17:04 dannyhw

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

hayata-suenaga avatar Oct 13 '23 10:10 hayata-suenaga

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

dannyhw avatar Oct 14 '23 14:10 dannyhw

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

nazmeln avatar Oct 18 '23 20:10 nazmeln

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

dannyhw avatar Oct 22 '23 20:10 dannyhw

should be resolved in latest versions

dannyhw avatar Mar 07 '24 13:03 dannyhw