I'm having problems upgrading a project from RN 55 to RN 58.6
(UPDATE: this also occurs on 59, repro: https://github.com/dslounge/rnDecorators59).
My project has been using styled-components for a long time and it worked well. As I'm upgrading this project to RN 58.6, the app breaks due to issues with the withTheme decorator and react-proxy. Here are a few screenshots:
The error I'm getting:

The error location. createClassProxy.js from react-proxy doesn't handle forwardRefs:

This is a sample of the code that breaks. (repro: https://github.com/dslounge/rnDecorators59)
import React from "react";
import { withTheme } from "styled-components/native";
import { Text, View } from "react-native";
// THIS DOESN'T WORK
@withTheme
export class Button extends React.Component {
render() {
const { theme } = this.props;
return (
<View>
<Text style={theme.buttonColor}>some text</Text>
</View>
);
}
}
//THIS WORKS:
// class ButtonUI extends React.Component {
// render() {
// const { theme } = this.props;
// return (
// <View>
// <Text style={{ color: theme.buttonColor }}>this should be red</Text>
// </View>
// );
// }
// }
// export const Button = withTheme(ButtonUI);
My babel configuration seems to be fine:
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-export-namespace-from"]
]
}
I don't quite understand why this would break with an upgrade. As far as I know, styled-components has been using forwardRefs for a long time, and react-proxy hasn't changed in a long time either. I can only think that the breaking change is the babel upgrade.
This was my babelrc before upgrading:
{
"presets": ["react-native-stage-0/decorator-support"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}
I'm not sure if react-native-stage-0/decorator-support behaves differently from @babel/plugin-proposal-decorators.
The only other thing I can think of is that there's some underlying change with Metro? I would love to understand what I'm missing here.
I've looked for answers, I haven't found much, but some people are having this issue:
Expected a constructor error.I've created a repo reproducing this issue: https://github.com/dslounge/rnDecorators59
I'm expecting my existing use of styled-components withTheme decorator to work just like it worked in RN 55.
Repo reproducing the issue: https://github.com/dslounge/rnDecorators59
React Native Environment Info:
System:
OS: macOS 10.14
CPU: (4) x64 Intel(R) Core(TM) i5-4278U CPU @ 2.60GHz
Memory: 292.31 MB / 8.00 GB
Shell: 5.3 - /bin/zsh
Binaries:
Node: 10.13.0 - ~/.nvm/versions/node/v10.13.0/bin/node
Yarn: 1.10.1 - /usr/local/bin/yarn
npm: 6.4.1 - ~/.nvm/versions/node/v10.13.0/bin/npm
Watchman: 4.7.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.1, macOS 10.14, tvOS 12.1, watchOS 5.1
Android SDK:
API Levels: 19, 21, 23, 24, 25, 26, 27, 28
Build Tools: 19.1.0, 23.0.1, 23.0.3, 24.0.3, 25.0.1, 25.0.2, 25.0.3, 26.0.1, 26.0.2, 26.0.3, 27.0.3, 28.0.2, 28.0.3
System Images: android-28 | Google Play Intel x86 Atom
IDEs:
Android Studio: 3.2 AI-181.5540.7.32.5014246
Xcode: 10.1/10B61 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.3 => 16.8.3
react-native: 0.59.5 => 0.59.5
It looks like you are using an older version of React Native. Please update to the latest release, v0.59 and verify if the issue still exists.
react-native info on a project using the latest release.
It seems that you're using custom babel config and it might be the cause.
Sorry, I guess I shouldn't have spent all that time describing the problem and recreating the issue in a repo.
I appreciate anyone taking their time to look at this issue. Thank you.
Let's not close this just yet. Upgrading past 0.56/0.57 is known to have some friction due to the upgrade to Babel 7. I'd like to hear more about @dslounge's specific situation in order to understand how this might affect other folks performing similar upgrades.
it seems like withTheme isn't exported from styled-components/native but rather from styled-components: https://snack.expo.io/@notbrent/vigorous-popsicle
edit: here's a full example with the App.js from the original issue included as well: https://snack.expo.io/@notbrent/vigorous-popsicle-lol
edit 2: perhaps this only confirms that the issue didn't exist as far back as 0.57 ;P
confirmed it's a React.forwardRef issue:
import React from "react";
import { Text, View } from "react-native";
// this works
function withLol(Component) {
class MyThemedThing extends React.Component {
render() {
return <Component theme={{buttonColor: 'green'}} {...this.props} />
}
}
return MyThemedThing;
}
// this doesn't work
function withForwardRef(Component) {
const WithForwardRef = React.forwardRef((props, ref) => {
return <Component theme={{buttonColor: 'green'}} {...props} ref={ref} />;
});
return WithForwardRef;
}
@withForwardRef
export class Button extends React.Component {
render() {
const { theme } = this.props;
return (
<View>
<Text style={{color: theme.buttonColor}}>some text</Text>
</View>
);
}
}
@brentvatne, does forwardRef work as expected when used without decorators? Does it work with decorators in a new project?
@TheSavior - it works without decorators, yeah (const Button = withForwardRef(BaseButton) works). by new project do you mean a blank react-native init project? this is basically what @dslounge provided but with decorator babel plugin enabled
I think it ultimately comes down to this line in react-proxy. https://github.com/gaearon/react-proxy/blob/1.x/src/createClassProxy.js#L102. I'm just not sure why this started acting up all of a sudden with a react-native upgrade.
Same problem here after start using yarn workspace.
When using single project (not monorepo), React.forwardRef was working fine. hmm...
I'm having this problem with 0.59, not using forwardRef but I am using MobX decorators...
Hey everyone, I was looking a bit closer at this issue today and I am concerned that this will affect more and more people, given that new versions of popular libraries like redux-react (v6 > v7 update) and mobx-react (v5 > v6 update) started using decorators.
I found that apparently the reason why this started happening after the react-native upgrade lies in Metro's HMR https://github.com/facebook/metro/issues/272
And (back in December!) @gaearon wrote that
Again, if there鈥檚 a bug or missing thing in react-proxy I鈥檇 be happy to take a fix and close this. Did anyone send a PR?
So my best guess would be that:
Sorry, I don't have a perfect solution for this atm 馃槗But I hope that the new information can help coming up with a plan 馃
We're going to get rid of react-proxy and that approach in the close future.
import { withTheme } from 'styled-components'
class SomeComp extends React.Component {
render() {
console.log(this.props.theme);
}
}
export default withTheme(SomeComp);
this works for me
react-proxy has been deleted in master.
We've replaced the transform with a different one that doesn't suffer from this issues.
The fix is expected to land in React Native 0.61.
See https://github.com/facebook/react-native/issues/18899#issuecomment-506881769 for details.
If you are having this issue when upgrading to RN 59, some of the workarounds written above might not work. You can change this line in node_modules/metro/src/lib/parseOptionsFromUrl.js and use patch-package
diff --git a/node_modules/metro/src/lib/parseOptionsFromUrl.js b/node_modules/metro/src/lib/parseOptionsFromUrl.js
index 3a55687..331bcc1 100644
--- a/node_modules/metro/src/lib/parseOptionsFromUrl.js
+++ b/node_modules/metro/src/lib/parseOptionsFromUrl.js
@@ -113,7 +113,7 @@ function parseOptionsFromUrl(reqUrl, platforms) {
options: {
customTransformOptions,
dev,
- hot: true,
+ hot: false,
minify,
platform,
onProgress: null,
In general I would recommend avoiding the use of decorators, as they're not a stable language feature yet. (Although, as I said, this specific problem will be fixed in 0.61)
In general I would recommend avoiding the use of decorators, as they're not a stable language feature yet. (Although, as I said, this specific problem will be fixed in 0.61)
I don't suppose you know how long we'll be waiting for the 0.61 release by any chance do you?
the cut of 0.61 will likely happen over the next couple weeks - sorry it's taking so long again :(
0.61 is out with a fix.
Most helpful comment
We're going to get rid of
react-proxyand that approach in the close future.