简体   繁体   中英

How to configure babel for react-relay (classic) on react-native 0.57+

I've been trying to upgrade react-native for our app from 0.52.0 to latest since 4th of january.

Up to 0.55.0 everything went fine (had some issues with 0.56.0 cause react-native-router-flux were incompatible), but when trying to go to 0.57.0 everything stopped working.

After fixing all other errors, no matter what I do I get this error:

Invariant Violation: RelayQL: Unexpected invocation at runtime. Either the Babel transform was not set up, or it failed to identify this call site. Make sure it is being used verbatim as `Relay.QL`.

This error is located at:
in RelayRenderer (at TabIcon.js:77)
in TabIcon (at navigationStore.js:245)
in RCTView (at View.js:44)
in AnimatedComponent (at CrossFadeIcon.js:34)
in RCTView (at View.js:44)
in TabBarIcon (at BottomTabBar.js:142)
...etc

(Btw: It's nothing special about that particular relay container; whatever container wrapped with a Relay.Renderer is called first will fail with the same error.)

As my code definitely uses verbatim Relay.QL in the relevant code, the issue obviously must be that the babel transform isn't working.

The old .babelrc that worked at least up to react-native 0.55.0:

{
  "presets": [
    "react-native",
    {
      "plugins": ["custom-relay"]
    }
  ]
}

The custom-relay is a small script that a previous developer copied from somewhere:

const getBabelRelayPlugin = require('babel-relay-plugin');
const schema = require('../../schema.json');

module.exports = getBabelRelayPlugin(schema.data);

After a few days of swearing I realized that even though the documentation and the react-native-git-upgrade script tells me to upgrade the .babelrc file; it appears that this file is completely ignored, so when I moved the config to a babel.config.js file instead at least I started getting new errors indicating that this file were used.

The custom-relay script turned out to be impossible to translate into something that is compatible with babel 7 since the deprecated babel-relay-plugin doesnt work with babel 7 and babel-plugin-relay doesn't export the correct methods; besides it's supposed to work without it now.

My current babel.config.js:

module.exports = function babelconfig(api) {
  api.cache(false);
  return {
    presets: ['module:metro-react-native-babel-preset'],
    plugins: [
      ['relay', { compat: true, schema: 'schema.json' }],
      '@babel/transform-runtime',
    ],
  };
};

I've also changed the .babelrc file to say the same (only in JSON syntax) for good measure, but it doesn't help.

Googling for this issue has been fruitless so far, the only issues and SO questions I've found seems to be related to older versions of react-native (or just react) and the solutions are generally variants of the old .babelrc config that no longer works such as ( 2206 , 1202 , 2025 , 1899 ). And I've been unable to find any babel config examples that both uses react-native 0.57.0 and babel 7 syntax as well as react-relay.

I once found a forum post or issue where someone mentioned something to indicate that migrating from Relay Classic to Relay Modern would work; but I can't remember where I found it; and since this migration is a massive undertaking in itself I'm not very eager to start doing that just to discover that the error message just changes from RelayQL: Unexpected invocation at runtime. to graphql: Unexpected invocation at runtime .

But if someone can confirm (with sources) that either react-native 0.57+ or babel 7 is definitely incompatible with relay classic syntax, and that migrating to modern will solve all my issues; of course I will do so.

I figured it out myself... Seems the issue was caused by incomplete documentation about how to use Relay Classic with newer versions. I've created an issue for this here .

If you're having the same issue as me, you're probably also using the "wrong" variable name Relay rather than RelayClassic when importing from react-relay/classic like me.

I changed:

import Relay from 'react-relay/classic';
//...
fragments: {
      viewer: () => Relay.QL`

to:

import RelayClassic from 'react-relay/classic';
//...
fragments: {
      viewer: () => RelayClassic.QL`

everywhere. And suddenly it started working again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM