relay: Nested fragments cause flow errors with relay modern

I’m currently experiencing an issue with flow generated prop types where I’m trying to use flow to set my prop types but I keep getting missing field errors for components that define fragments. It looks like relay-compiler (as of version 1.5+) is generating the correct types with fragmentRef’s, but they do not appear to be working as I would expect.

I used the todo-mvc app to show my problem: https://github.com/cdriscol/relay-todomvc/tree/found-modern-flow

I essentially have the following changes:

// @flow
// TodoApp.js
// ...
import type { TodoApp_viewer } from './__generated__/TodoApp_viewer.graphql';
type Props = {
	viewer: TodoApp_viewer,
	children: any,
	relay: any
};

class TodoApp extends React.Component<Props> {
// ...
<TodoListFooter viewer={viewer} />
// ...
}
// @flow
// TodoListFooter.js
//....
import type { TodoListFooter_viewer } from './__generated__/TodoListFooter_viewer.graphql';

type Props = {
  viewer: TodoListFooter_viewer,
  relay: any,
};

class TodoListFooter extends React.Component<Props> {
//...
}

What I’m seeing is 5 errors on the TodoApp.js, one of which is the following…

Error: src/components/TodoApp.js:42
 42:           <TodoListFooter viewer={viewer} />
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ props. This type is incompatible with
 14: class TodoListFooter extends React.Component<Props> {
                                                  ^^^^^ Props. See: src/components/TodoListFooter.js:14
  Property `viewer` is incompatible:
     42:           <TodoListFooter viewer={viewer} />
                                           ^^^^^^ TodoApp_viewer. This type is incompatible with
     10:   viewer: TodoListFooter_viewer,
                   ^^^^^^^^^^^^^^^^^^^^^ TodoListFooter_viewer. See: src/components/TodoListFooter.js:10
      Property `__fragments` is incompatible:
         42:           <TodoListFooter viewer={viewer} />
                                               ^^^^^^ property `__fragments`. Property not found in
         10:   viewer: TodoListFooter_viewer,
                       ^^^^^^^^^^^^^^^^^^^^^ TodoListFooter_viewer. See: src/components/TodoListFooter.js:10

I’m wondering why flow cannot handle this case, as the generated flow types do seem to look correct and reference the correct fragment.

// TodoApp_viewer.graphql.js
/*::
import type { ConcreteFragment } from 'relay-runtime';
type TodoListFooter_viewer$ref = any;
import type { FragmentReference } from 'relay-runtime';
export opaque type TodoApp_viewer$ref: FragmentReference = FragmentReference;
export type TodoApp_viewer = {|
  +id: string,
  +__fragments: TodoListFooter_viewer$ref,
  +$refType: TodoApp_viewer$ref,
|};
*/
// TodoListFooter_viewer.graphql.js
/*::
import type { ConcreteFragment } from 'relay-runtime';
import type { FragmentReference } from 'relay-runtime';
export opaque type TodoListFooter_viewer$ref: FragmentReference = FragmentReference;
export type TodoListFooter_viewer = {|
  +todos: ?{|
    +edges: ?$ReadOnlyArray<?{|
      +node: ?{|
        +id: string,
        +complete: ?boolean,
      |},
    |}>,
  |},
  +id: string,
  +numTodos: ?number,
  +numCompletedTodos: ?number,
  +$refType: TodoListFooter_viewer$ref,
|};
*/

Sorry for the long explanation and lots of code pasting, I just can’t seem to figure out why flow is complaining about the generated types… maybe I’m missing something here?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 37 (11 by maintainers)

Most upvoted comments

The best workaround as far I know.

screen shot 2018-04-08 at 04 56 59

Dont use the __generated__ type definitions. Use your own types, which are basically a copy of the schema types.

Works great fo me!

Yup, #2293 will allow fragment reference type checking without using haste 👍

related to https://github.com/facebook/relay/issues/2394

I think @alloy PR https://github.com/facebook/relay/pull/2293 could solve some of this issues

@jstejada any progress on that merge?

The issue is still happening even though the documentation says it works. It’s most likely because the flow-typed definitions for createFragmentContainer are incorrect. Since it’s working correctly at Facebook, it would be much appreciated if someone working at Facebook could share the flow definitions Facebook uses. Thanks.