-
-
Notifications
You must be signed in to change notification settings - Fork 159
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
Promise.finally is being overwritten in React Native #20
Comments
in case anyone didn't figure out this simple temp fix. // temp fix for the promise.finally
// https://github.com/storybookjs/storybook/issues/8371
const fn = Promise.prototype.finally
const StoryBook = require('./storybook')
Promise.prototype.finally = fn |
Hello, thank you for this
|
@odjhey The only reason why I can think of for why this wouldn't work is that the version of node you're using doesn't support it. But if the |
Hey there @tjbenton, what if you are running storybook as a View contained in an app? Doing the same as you did, before/after the imports doesn't change it. Minor update: If I do your tmp fix on |
Hey, |
@Gongreg Thanks for looking into this, I appreciate it’s a tricky problem. Hopefully someone can find a solution soon. |
The longer term solution is we are going to try splitting out react native storybook out of monorepo, so we will be able to change build setup. But that will take time. If anyone has any short term ideas it would be great, because I am also experiencing the issue in our own project. :/ |
Gadzooks!! I just released https://github.com/storybookjs/storybook/releases/tag/v5.3.0-alpha.42 containing PR storybookjs/storybook#8698 that references this issue. Upgrade today to try it out! You can find this prerelease on the Closing this issue. Please re-open if you think there's still more to do. |
@shilman this issue is a lot bigger actually :| All of the packages that are used in React Native shouldnt have any polyfills. We cant think of an easy solution with @ndelangen . Maybe we could just add the polyfills in entry files for manager/preview and skip them in lib/addons? |
A good set it and forget it workaround for this issue is a combination of the solutions presented by @tjbenton and @limaAniceto above with patch-package:
vi node_modules/@storybook/react-native/dist/index.js
var fnFix = Promise.prototype.finally;
/*original code*/
Promise.prototype.finally = fnFix;
yarn patch-package @storybook/react-native && git add patches This will ensure you do not include in your project patches to modules, that the package is always patched for every developer in your team and can even be included in CI/CD pipelines and containers. The diff is saved in a |
This issue just cost me a night and a morning trying to hunt down what was going on, so to find out it's a storybook issue and it's been known about really has steam coming out of my ears. |
@colinta You’ve just reminded me this issue exists, I was hoping with version 6 this may have been closed. Shame if it’s still hanging around. |
looking into a fix for this, seems like just changing the babel config could resolve this. __ edit: maybe not as simple as expected still investigating |
This is from corejs and it seems like the problem starts with storybook core because even if I remove all the old polyfills from the @storybook/react-native config then it still happens. The babel preset env polyfill will cause this when ever 'core-js/modules/es.promise' gets imported, see the following issues: |
@dannyhw any updates? has this been fixed? |
@apedroferreira unfortunately not since the issue is upstream I wasn't able to make progress on this. I'm hoping that maybe upgrading dependencies to 6.0+ will help. I'll test it in the 6.0 upgrade branch. From what I understand there would need to be a version of storybook client that isn't polyfilled or at least with a different browser target. So I think a workaround is the best chance we have for now, however I will raise the issue on the storybook repo to see if we can look into it. Edit: In the past I did also try applying the workaround above to the project and it doesn't seem to work for me |
@dannyhw Today, after doing an upgrade of the Expo SDK (40), the same error appeared. After some investigations, more or less dumb tries of making my app working, I discovered something quite interesting. If I add That means that if I want to work on my app, I need to add this import after every bundle reload. And if I want to ship it in production, I need to do the same procedure before doing any build. I desperately need help. I honestly don't know what to do with this info but maybe someone will. Btw, the above workaround did work for a while, but only for a while. I'm now quite stuck with this error and don't have any clue on how to get my app working. Any fix or workaround would be HUGELY appreciated. |
Ok I managed to get my app working ! Adding an import of In my case, I had to import Anyway, some consideration about this issue from the Storybook team would be highly appreciated, since any RN developer working with promise based libs (e.g. @apollo/client 3.x) will be facing the same issue... |
@ajacquierbret hey thanks for posting your workaround hopefully that will save some people a lot of frustration. I've tried different things in the past to resolve this and the proper fix always seems to require changes upstream. It's hard to coordinate these changes since it's only rn with this problem. I think in the web versions it's fixed via webpack wizardry. I was kind of hoping that 6.0 might fix this but I'm not sure yet. I'll try it out in the upgrade branch soon. |
Posting in case I can help save someone a few hours of their time, it looks like this polyfill behaviour of Storybook breaks Example in a native Android module @ReactMethod
fun multiply(a: Int, b: Int, promise: Promise) {
promise.resolve(a * b)
} Importing any part of Storybook in a project breaks the above example (the promise is never resolved on the RN/JS side), e.g. import {getStorybookUI} from '@storybook/react-native';
getStorybookUI({});
// The following will now never resolve (but did work prior to the inclusion of Storybook)
AwesomeModule.multiply(3,7).then(...); // or
(async () => { const res = await AwesomeModule.multiply(3,7); ... })(); MVP repo with screenshots, basic example bootstrapped using Have tried the potential fixes mentioned in this thread, but currently I've been unsuccessful in figuring a way around the issue. |
Following the approach of @defrex comment i've been able to get it to work with react lazy and suspense: StorybookScreen.tsx const StorybookUI = lazy(() => import('../../storybook'));
const StorybookScreen: React.FC = () => {
return (
<Suspense fallback={<Text> loading </Text>}>
<StorybookUI />
</Suspense>
);
}; App.tsx const App: React.FC = () => (
{ __DEV__? <StorybookScreen/> : <App/> }
); |
In this PR I demonstrate how you can use patch package to fix this error. Basically just this patch for @storybook/addons
|
This polyfill breaks Promise when we render Storybook, because they will never resolve. See this comment from the storybook/react-native maintainer on GitHub: storybookjs/react-native#20 (comment)
This polyfill breaks Promise when we render Storybook, because they will never resolve. See this comment from the storybook/react-native maintainer on GitHub: storybookjs/react-native#20 (comment)
This polyfill breaks Promise when we render Storybook, because they will never resolve. See this comment from the storybook/react-native maintainer on GitHub: storybookjs/react-native#20 (comment)
None of the proposed fixes work. Not even after restarting the metro server. Removing the import from @storybook/addons/dist/index.js causes a stack exceed exception on app start. I also tried not to call At this state the lib is not usable if it destroys the RN promise implementation. The only way to get this to work is to use a timeout (of 10 ms) before loading any storybook code. function StorybookScreen() {
const [storybookUI, setStorybookUI] = React.useState<ReactNode | null>(null)
useEffect(() => {
if (!__DEV__) {
return
}
// eslint-disable-next-line @typescript-eslint/no-var-requires
const timer = setTimeout(() => {
const { StorybookUI } = require("../storybook")
setStorybookUI(<StorybookUI />)
}, 10)
return () => clearTimeout(timer)
}, [setStorybookUI])
return (
<>
{storybookUI}
</>
)
}
`` |
@pke patching the addons dependency to remove the corejs promise polyfill works as a workaround as far as I know. Also there was a new version yesterday to fix some issues in the latest version of react native, not sure if its related to any issues you're having. |
Removing the polyfill didn't work in my setup. I tried for hours. It worked in hot reload sometimes but not deterministic. Cold boot the app never worked. The timeout works. It's clearly a race condition and my setup might be slower or faster than the rest of the ones who tries the workarounds. I am on a fairly old RN version 66.3 and I still don't understand how the polyfill can even be active when RN provides a complete es6 promise including finally. I'd like to understand how the polyfill works. In the corejs I found related bug and they clearly stated the way storybook authors use the polyfills is wrong. They shouldn't be imported from the modules folder. |
@pke in the v6 beta we get around this problem by resolving to the modern build of storybook (bundled as sbmodern) |
now just checking back with my app its not working again... haha seems to be clock related or something weird. |
The server is not ready and probably won't be for some time. I don't really know how to make it work for v6 and if I were to recreate it I'd probably opt for implementing something a bit different. As always if someone is willing to figure it out then I'll happily take a PR but I've tried a few times and it seems to not be compatible without making a lot of changes. |
I tried again removing the import and now it corejs runs into a stack overflow cause no promise seems to be defined and it uses some alternative setTimeout path or so. That is on RN 66.3 |
@pke if you have a reproduction I can try to debug it for you. |
Thanks @dannyhw, I can't produce a version where its easily reproducable, thats the problem. It seems to be totally random. |
Hey, I tried upgrading to Storybook 6 and I still experience this problem with Apollo-client. Removing storybook fixes the issue. Any idea what to do?
|
@Waltari10 make sure you add the metro config to resolve sbmodern. |
An alternative solution that should work for any version is to configure Metro so that it doesn't load the polyfill that Storybook packages load. Inside const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (moduleName.startsWith('core-js/modules/es.promise')) {
// Storybook patches Promise and removes finally, causing errors throughout the application
// This configures it so that the offending package isn't loaded when requested
return {
type: 'empty',
};
} else {
return context.resolveRequest(context, moduleName, platform);
}
};
module.exports = config; |
Is there a more up-to-date solution to this? I'm trying to use |
I have updated to the latest version, as I saw in a changelog that this issue was fixed, however it persists in my case
In |
@tj-mc what version are you using? Its only fixed in 6.5. |
Turns out I needed to upgrade the other
In
The last 3 values are the default for React Native. And for the record, this is an ejected Expo app. Now working fine without any errors. Thank you for your work on this! ❤️ If you were previously using the above custom-resolver fix, you can now delete it 😄 |
Describe the bug
The inclusion of Storybook inside a React Native app seems to remove the implementation of
Promise.prototype.finally
. Causing thePromise.resolve(...).finally is not a function error
to occur.To Reproduce
Steps to reproduce the behavior:
npx -p @storybook/cli sb init --type react_native
(no server)toString
onPromise.prototype.finally
but after importing Storybook (you have to userequire
in this instance, notimport
, so the ordering works for the test to see thatfinally
starts off being an actual function) it’s no undefined.Example repo here, https://github.com/benjaminreid/SBPromiseTest
Expected behavior
Promise.prototype.finally
to no be removed.Screenshots
N/A
Code snippets
finally
is valid here, but after the inclusion of Storybook, it’sundefined
.System:
Additional context
In my instance
redux-persist
use this in theironBeforeLift
callback.The text was updated successfully, but these errors were encountered: