Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fragment cannot be spread here as objects of type "Query"

Trying out relay with react and ran into this today. Here is what I've done so far.

Root Query:

query {
  tasks {
    id
    taskName
    taskStatus
    userId
  }
}

React component hierarchy

App   
 ↳--TaskList (props: tasks)
    ↳--TaskListItem (props: task)

Now due to the principle of colocation I know I have to write fragments in each component to describe their data needs.

TaskListItem.js

const TaskListItemContainer = createFragmentContainer(
    TaskListItem,
    graphql`
        fragment TaskListItem_task on task {
            id
            taskName
            taskDone
            authorId
        }
    `
);

TaskList.js

const TaskListContainer = createFragmentContainer(
    TaskList,
    graphql`
        fragment TaskList_tasks on task {
            tasks {
                ...TaskListItem_task
            }
        }
    `
);

App.js

<QueryRenderer
   environment={relayEnvironment}
   query={graphql`
       query AppQuery {
         ...TaskList_tasks
       }
     `
   }

When I run the relay compiler I get the following error.

Fragment "TaskList_tasks" cannot be spread here as objects of type "Query" can never be of type "task".

App.js (3:15)
2:             query AppQuery {
3:               ...TaskList_tasks
                 ^
4:             }

Not able to figure out how to organize the structure because of this problem. Should I modify the schema just to facilitate the structure and reuse of fragments on the client side?

like image 885
Giridhar Karnik Avatar asked Apr 22 '19 16:04

Giridhar Karnik


1 Answers

A basic Fragment consists of five things:

  • the fragment keyword
  • the name of the Fragment
  • the on keyword
  • the type the Fragment applies to
  • the selection set wrapped in a set of curly brackets

The selection set is one or more fields of the type you specify that you want to request when you use the Fragment. Think of the Fragment as a drop in replacement for a single selection set. If I have a query like this:

query {
  foo
  bar
}

then { foo bar } is the selection set I'm requesting, in this case on the Query type (or whatever your query root operation type is called in your schema). So if I want to use a fragment, I would write:

query {
  ...QueryFields
}

fragment QueryFields on Query {
  foo
  bar
}

In your code, you're trying to write a query like:

query {
  ...TaskList_tasks
}

However, as the error indicates, the type associated with the TaskList_tasks fragment is task. But you're not replacing a selection set for a task type here, you're replacing a selection set for the Query type. So your request is not valid.

TLDR; You need to change the type on your Fragment to Query:

fragment TaskList_tasks on Query {
  tasks {
    ...TaskListItem_task
  }
}
like image 131
Daniel Rearden Avatar answered Nov 03 '22 01:11

Daniel Rearden