Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the @include and @skip directives #245

Closed
vladar opened this issue Sep 5, 2015 · 19 comments
Closed

Support the @include and @skip directives #245

vladar opened this issue Sep 5, 2015 · 19 comments
Assignees

Comments

@vladar
Copy link

vladar commented Sep 5, 2015

I tried to add directives to my GraphQL query in Container, like:

Relay.createContainer(Component, {
  initialVariables: {
    showField1: true
  },
  fragments: {
    test: (variables) => Relay.QL`
      fragment on SomeType {
        field1 @include(if: $showField1) {
          ...
        }
        field2 @skip(if: $showField1) {
          ...
        }
      }
    `
  }
})

But they were cut out by Relay. Am I missing something?

@josephsavona
Copy link
Contributor

@vladar Thanks for filing an issue - Relay doesn't support arbitrary directives (it uses the @relay(...) directive for some metadata). This is definitely something we would like to support going forward.

@vladar
Copy link
Author

vladar commented Sep 6, 2015

Thanks for clarifications. But @include and @skip are not arbitrary. They are part of GraphQL specification - http://facebook.github.io/graphql/#sec--skip

@josephsavona josephsavona self-assigned this Sep 6, 2015
@josephsavona
Copy link
Contributor

@vladar touche. yes, we should support these. I'll update the title of this issue to reflect this.

@josephsavona josephsavona changed the title Q: does Relay support directives? Support the @include and @skip directives Sep 6, 2015
@AndrewIngram
Copy link

Is it necessary for Relay to be cutting out the directives? Presumably if they were left intact it would be possible to support arbitrary ones as well.

@wincent
Copy link
Contributor

wincent commented Sep 8, 2015

@AndrewIngram, that's a good point. I think the reason we've defaulted to a conservative policy here so far is that directives can drastically alter the semantics of a query, and Relay very much wants to be able to both statically analyze component queries and dynamically construct new ones at runtime (for example, to compute minimal diff queries in order to request only data that is not already present in the store).

In addition to that, directives as they exist in open source GraphQL are a relatively new addition to the language, so support for them is still pretty recent and basic.

But yes, we should not only handle directives in the spec, but also consider what the implications of "passing through" any other directives that we don't explicitly support might be.

@AndrewIngram
Copy link

Incidentally, this is the use case I'm trying to support:

const UserSearchContainer = Relay.createContainer(UserSearch, {
  initialVariables: {
    query: null
  },
  fragments: {
    viewer: (variables) => Relay.QL`
      fragment on User {
        first_name
        users (
          q: $query
          first: 10
        ) @include(if: $query) {
          edges {
            node {
              ${UserSearchList.getFragment('users')}
            }
          }
        }
      }
    `,
  }
});

At the moment, I'm handing this by making the users connection return a promise with an empty array if there's no query. But ideally we wouldn't even be hitting that part of the graph at all

@grydstedt
Copy link

+1

@josephsavona
Copy link
Contributor

This is fixed in master and will be available in the next release :-)

@emilsjolander
Copy link

Did this make it into the latest release? I'm currently using 0.3.2 but it seems to be ignoring the include directives still.

@kassens
Copy link
Member

kassens commented Sep 29, 2015

cc @josephsavona

@aweary
Copy link
Contributor

aweary commented Oct 5, 2015

Any word on this? @josephsavona doesn't seem to be working for me either.

@guigrpa
Copy link

guigrpa commented Oct 9, 2015

@josephsavona I can confirm it: the @include directive is apparently ignored

@josephsavona
Copy link
Contributor

@guigrpa @aweary Do you mean that the queries are sent to the server without directives that were specified in a container fragment? Or are the directives there but are being ignored (e.g. Relay gives you the data even though the directive says to skip, or vice-versa)?

@aweary
Copy link
Contributor

aweary commented Oct 10, 2015

From what I saw the babel plugin just returned an error for the fragment, which was then called.

@josephsavona
Copy link
Contributor

@aweary can you provide the fragment itself and the error message & stack (if present)?

@guigrpa
Copy link

guigrpa commented Oct 10, 2015

Here's what I am seeing: this is the fragment:

  initialVariables: {
    projectId: null,
  },
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        ${SelectProject.getFragment('viewer')}
        node(id: $projectId) @include(if: $projectId) {
          ${ProjectDetails.getFragment('project')}
        }
      }
    `,
  },

The query that's being sent includes the node field without an id arg, so the GraphQL server returns an error: "Field \"node\" argument \"id\" of type \"ID!\" is required but not provided." The Relay client shows a warning (Warning: fetchWithRetries: HTTP error, retrying.) and then retries and retries...

@josephsavona
Copy link
Contributor

@guigrpa I see what's happening - this is not about directives.

Relay requires that the node(id: $id) field be on the root - see the Object Identification guide. It appears that your schema nests this field inside a Viewer type, and this nesting is not supported by Relay. Containers should fetch data for any object of a type (in this case the fragment should probably be project => Relay.QLfragment on ProjectDetail { ... }``). See the routes guide for more information about this important distinction.

As for why it isn't working now, GraphQL is rejecting the query since $projectId is null. A better pattern would be to have separate fragments for viewer and project (which would use the node root query).

@aweary
Copy link
Contributor

aweary commented Oct 10, 2015

@josephsavona I should note that the error I was getting was due to using the @include directive in an inline fragment which I already noted here: #443

If I use it on each field it seems to be working just fine 👍

@josephsavona
Copy link
Contributor

Thanks everyone for confirming that directives themselves are working as-expected. I'll leave this issue closed.

@guigrpa - please feel free to ask follow-up questions about the node field and route/container distinction on Stack Overflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants