46

I'm trying to type (with flowtype) the components I'm enhancing with Relay.createContainer.

I looked into the types exported by the "react-relay" package but ReactContainer doesn't seem to carry over Props.

I experimented with RelayContainer, ReactClass, React$Component etc, in the end the closest thing to the expected result I could get is :

// Foo.js
// @flow
import React from "react";
import Relay from "react-relay";

type Props = { title: string; }
const Foo({ title }: Props) => (<div>{title}</div>);

const exported: Class<React$Component<void, Props, void>> = Relay.createContainer(Foo, {
  fragments: { ... }
});

export default exported;

--

// Bar.js
// @flow

import React from "react";
import Foo from "./Foo.js";
const Bar = () => <Foo />; 

Now flow will complain in Foo.js around Props that Bar doesn't provide the title prop, which kinda what I want (I'd like it to complain in Bar.js but it's a detail). However if Bar was also a RelayContainer referencing Foo's fragment flow would complain that it can't find getFragment in Foo's properties:

// Bar.js
// @flow

import React from "react";
import Relay from "react-relay";
import Foo from "./Foo.js";

const Bar = () => <Foo />; 

export default Relay.createContainer(Bar, {
  fragments: {
    baz: () => Relay.QL`
      fragment on Baz {
        ${Foo.getFragment("foo")}
      }
    `
  }
}

In the end I'm trying to type the output of Relay.createContainer so that it carries over the typing of the decorated component. I looked into the Relay's internal types and saw https://github.com/facebook/relay/blob/8567b2732d94d75f0eacdce4cc43c3606960a1d9/src/query/RelayFragmentReference.js#L211 but I feel like it's not the way to go to add in Relay's properties.

Any idea how could I achieve this ?

Maksim Kalmykov
  • 1,189
  • 3
  • 18
  • 24
chollier
  • 892
  • 1
  • 7
  • 8
  • 2
    related https://github.com/facebook/relay/pull/1155 – gre Nov 22 '16 at 10:17
  • The outline above seems promising. I'm going to see if I can augment it to tell Flow that the higher order component adds a static getFragment method. If anyone has come up with a better alternative, it would be nice to learn! – John Mar 15 '17 at 00:17
  • 1
    Lee Byron announced yesterday at react-europe that Relay 1.0.0 will generate __generated__/* files for each fragment and that they will export flowtypes. so I guess this will solve this? – gre May 20 '17 at 07:40

1 Answers1

4

as @gre pointed out, now the Relay Compiler generates Flow types for the fragment and these are exported in generated files within a __generated__ subdirectory.

generating said file by running the Relay Compiler

relay-compiler --src ./src --schema ./schema.json

You would then import the flow types for the field props like so:

import type { MyComponent_myField } from "./__generated__/MyComponent_myField.graphql";
class MyComponent extends Component<{
  myField: MyComponent_myField,
}> {
  render() {
    return <div>Example</div>;
  }
}
export default createFragmentContainer(MyComponent, {
  myField: graphql`
    fragment MyComponent_myField on MyType {
       edges {
          node {
            _id
            foo
          }
       }
    }
  `
});

Although AFAIK currently types for spreaded fragments are not generated unless you use the Haste module system

Alfonso Pérez
  • 2,985
  • 2
  • 24
  • 44