1

I'm running into an really bizarre TypeError with react-relay when trying to instantiate a class that extends Relay.Mutation. I've created a simple Typescript project with create-react-app my-app --scripts-version=react-scripts-ts to demonstrate the issue.

Whenever I run yarn start, this is what I'm seeing:

Relay.Mutation instantiation error

This error doesn't really make sense to me: TypeError: Object prototype may only be an Object or null: undefined

I'm just trying to instantiate a new instance of my own extended Relay.Mutation class. I'm really new to the React Relay world and ES6/Typescript in general so it's likely something silly I'm just missing.

In this simple project I'm using the example class directly as defined in the DefinitelyTyped repository.

Shouldn't I be able to use the class like so:

const atm = new AddTweetMutation({ text: 'asdf', userId: '1123' });

Here is what the AddTweetMutation.tsx class looks like:

import * as Relay from 'react-relay';

interface Props {
  text: string;
  userId: string;
}

interface State {
}

export default class AddTweetMutation extends Relay.Mutation<Props, State> {

  public getMutation() {
    return Relay.QL`mutation{addTweet}`;
  }

  public getFatQuery() {
    return Relay.QL`
            fragment on AddTweetPayload {
                tweetEdge
                user
            }
        `;
  }

  public getConfigs() {
    return [{
      type: 'RANGE_ADD',
      parentName: 'user',
      parentID: this.props.userId,
      connectionName: 'tweets',
      edgeName: 'tweetEdge',
      rangeBehaviors: {
        '': 'append',
      },
    }];
  }

  public getVariables() {
    return this.props;
  }
}

Here is the the entire Hello.tsx React component:

import * as React from 'react';
import AddTweetMutation from '../mutations/AddTweetMutation';

export interface Props {
  name: string;
  enthusiasmLevel?: number;
}

class Hello extends React.Component<Props, {}> {
  render() {

    const atm = new AddTweetMutation({ text: 'asdf', userId: '1123' });
    console.log(atm);

    const { name, enthusiasmLevel = 1 } = this.props;

    if (enthusiasmLevel <= 0) {
      throw new Error('You could be a little more enthusiastic. :D');
    }

    return (
      <div className="hello">
        <div className="greeting">
          Hello {name + getExclamationMarks(enthusiasmLevel)}
        </div>
      </div>
    );
  }
}

export default Hello;

// helpers

function getExclamationMarks(numChars: number) {
  return Array(numChars + 1).join('!');
}

This is what my package.json looks like:

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@types/jest": "^20.0.6",
    "@types/node": "^8.0.19",
    "@types/react": "^16.0.0",
    "@types/react-dom": "^15.5.2",
    "@types/react-relay": "^0.9.13",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-relay": "^1.1.0",
    "react-scripts-ts": "2.5.0"
  },
  "devDependencies": {},
  "scripts": {
    "start": "react-scripts-ts start",
    "build": "react-scripts-ts build",
    "test": "react-scripts-ts test --env=jsdom",
    "eject": "react-scripts-ts eject"
  }
}

Here's the project to github

Update: The typings are not currently valid for react-relay > 1.x. Please see the thread on github for this issue. I have also updated my repo with the workaround.

Justin Levi Winter
  • 2,327
  • 2
  • 17
  • 30
  • Check if `Relay.Mutation` actually exists. The version of the library and the typings doesn't match. Do a `console.log('relay.mutation', Relay.Mutation)` (or with ``) to find out. – unional Aug 06 '17 at 19:38
  • You're right. `Relay.Mutation` returns undefined. There doesn't seem to be a typings that matches the version of the library. What's the correct approach to fixing this? Why would Mutation no longer exist? Sorry, super new to Typescript and just trying to figure out a working strategy. – Justin Levi Winter Aug 06 '17 at 20:07
  • I'm assuming it has something to do with React v15.5 here: https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html – Justin Levi Winter Aug 06 '17 at 20:28
  • https://facebook.github.io/relay/docs/api-reference-relay-proptypes.html --- If I downgrade to : `"react-relay": "^0.9.*"` and `"@types/react-relay": "^0.9.13"` I can get past the error, but now I get a warning: lowPriorityWarning.js:40 Warning: Accessing PropTypes via the main React package is deprecated... I don't see an obvious solution for the latest versions??? – Justin Levi Winter Aug 06 '17 at 20:35

1 Answers1

1

The problem is that react-relay@1.1.0 has changed its API and @types/react-relay@0.9.13 is outdated.

TypeScript statically analyze your code based on the typings (type definitions) available. So even thou @types/react-relay@0.9.13 is outdated, TypeScript doesn't know and just act based on it.

To solve this problem, you can either:

For the last option, do this:

// custom-typings/react-relay.d.ts
declare module 'react-relay'

// tsconfig.json
{
  "include": [
    "custom-typings"
  ]
}
unional
  • 14,651
  • 5
  • 32
  • 56