使用Relay& amp;取决于根节点上的分页Graphql

时间:2018-02-26 06:55:30

标签: javascript node.js graphql relayjs relaymodern

努力争取这个设置并将我的头靠在墙上。我的GraphQL DB有以下结构:

Graphql Schema

let Schema = () => {

  let {nodeInterface, nodeField} = nodeDefinitions(
    (globalId) => {

      var {type, id} = fromGlobalId(globalId);
      if (type === 'Grant') {
        return GrantModel.findById(id);
      } else if (type === 'Scope') {
        return ScopeModel.findById(id);
      } else {
        return null;
      }
    },
    (obj) => {
      if (obj instanceof ScopeModel) {
        return scopeType;
      } else if (obj instanceof GrantModel)  {
        return grantType;
      } else {
        return null;
      }
    }
  );


  let grantType = new GraphQLObjectType({
    name: 'Grant',
    fields: () => ({
      id: globalIdField('Grant'),
      name: {type: GraphQLString},
      description: {type: GraphQLString}
    }),
    interface : [nodeInterface]
  });

  let scopeType = new GraphQLObjectType({
    name:'Scope',
    fields: () => ({
      id: globalIdField('Scope'),
      description: {type: GraphQLString},
      name: {type: GraphQLString},
      enabled: {type: GraphQLBoolean},
      grants: {type: new GraphQLList(grantType)}
    })
  });


  let {connectionType: scopeConnection} = connectionDefinitions({nodeType: scopeType});

  let viewerType = new GraphQLObjectType({
    name: 'Viewer',
    fields: () => ({
      scopes: {
        type: scopeConnection,
        args: connectionArgs,
        resolve: async (scope, args) => connectionFromArray(await ScopeModel.find({}), args)
      }
    })
  });

  let schema = new GraphQLSchema({
    query: new GraphQLObjectType({
      name: 'Query',
      fields: () => ({
        viewer: {
          type: viewerType,
          resolve: () => {}
        }
      })
    })

    /*mutation: new GraphQLObjectType({
      name: 'Mutation',
      fields: () => ({
        incrementCounter: {
          type: GraphQLInt,
          resolve: () => 4
        }
      })
    })*/

  });

  return schema;
}

export default Schema;

我有以下反应成分;请注意,我的index.js是我的根组件,然后是ScopeList.js,然后是Scope.js

index.js

const IndexQueryPage = graphql`
  query IndexQuery {
    viewer {
      ...ScopeList_scopes
    }
  }
`;

class Index extends React.Component {
  render () {
    return (
      <div className="container">
        <table className="table">
          <thead>
            <tr>
              <th>Date Added</th>
              <th>Service</th>
              <th>Description</th>
              <th>Enabled</th>
            </tr>
          </thead>
          <QueryRenderer
           environment={environment}
           query={IndexQueryPage}
           variables={{}}
           render={({error, props}) => {
             console.log(props);
             if(error) {
               return <tbody><tr><td colSpan='4'></td></tr></tbody>;
             }
             if(!props) {
               return <tbody><tr><td colSpan='4'>Loading.....</td></tr></tbody>;
             }
             return (
               <ScopeList scopes={props.scopes} />
             )
           }}
          />
        </table>
      </div>
    )
  }
}

module.exports = Index;

ScopeList.js

class ScopeList extends React.Component {
  render() {
    return (
      <tbody>
       {
         this.props.scopes.edges.map(edge => <Scope scope={edge.node} key={edge.node.cursor} />)
       }
      </tbody>
    )
  }
}

module.exports = createPaginationContainer(ScopeList, graphql`
  fragment ScopeList_scopes on Viewer
  @argumentDefinitions(
    count: {type: "Int", defaultValue: 10}
    cursor: {type: "String"}
  )
  {
    scopes (
      first: $count
      after: $cursor
    ) @connection(key: "ScopeList_scopes") {
      edges {
        cursor
        node {
          id
          name
          description
        }
      }     
    }
  }`,
  {
    direction: 'forward',
    getConnectionFromProps(props) {
      return null;
    },
    // This is also the default implementation of `getFragmentVariables` if it isn't provided.
    getFragmentVariables(prevVars, totalCount) {
      return {
        ...prevVars,
        count: totalCount,
      };
    },
    getVariables(props, {count, cursor}, fragmentVariables) {
      return {
        count,
        cursor
      };
    },
    query: graphql`
      query ScopeListQuery(
        $count: Int!
        $cursor: String
      ){
        ...ScopeList_scopes @arguments(count: $count, cursor: $cursor)
      }
   `}
);

Scope.js

class Scope extends React.Component {
  render() {
    return (
      <tr key={this.props.scope.id}>
        <td>{this.props.scope.name}</td>
        <td>{this.props.scope.description}</td>
        <td></td>
        <td></td>
      </tr>
    )
  }
}

module.exports = createFragmentContainer(Scope, graphql `
  fragment Scope_scope on Scope {
    id
    name
    description
  }
`);

基本上我正在尝试在根节点scopes上设置分页但是,我的理解是我需要通过将其作为子项添加到viewer来将其解耦为根。但是,我收到以下错误:

ERROR in ./app/pages/Index.js
Module not found: Error: You supplied a GraphQL document with validation errors:
component/ScopeList.js: Fragment "ScopeList_scopes" cannot be spread here as objects of type "Query" can never be of type "Viewer".
 @ ./app/pages/Index.js 28:8-53
 @ ./app/component/App.js
 @ ./app/index.js

1 个答案:

答案 0 :(得分:1)

不能在Viewer类型的查询的根目录上传播Query类型的片段。将该片段传播到查询的viewer字段