【问题标题】:Client-side query mocking with Apollo 2.0, react-apollo, and apollo-link-schema使用 Apollo 2.0、react-apollo 和 apollo-link-schema 进行客户端查询模拟
【发布时间】:2018-07-23 08:26:50
【问题描述】:

我希望能够在客户端模拟一些查询,这样我就不必提供 GraphQL 端点来处理我的 React 应用程序。

根据 Apollo 文档,看起来我应该使用 apollo-link-schema。我尝试按照示例进行操作,但在我的情况下,我最终遇到错误:Network error: Expected undefined to be a GraphQL schema. 在尝试访问包装组件内的查询结果时。

有人可以帮我理解我在这里做错了什么吗?

这是一个完整的 index.js 示例来说明我的问题:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { SchemaLink } from "apollo-link-schema";
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloCache } from 'apollo-cache';

import gql from 'graphql-tag';
import { graphql } from 'react-apollo';

import { makeExecutableSchema, addMockFunctionsToSchema, MockList } from 'graphql-tools';
const typeDefs = `
type Query {
  me: Person!
}

type Person {
    name: String!
}
`;
const schema = makeExecutableSchema({ typeDefs });
addMockFunctionsToSchema({ schema });

const schemaLink = new SchemaLink(schema);
const client = new ApolloClient({
    link: schemaLink,
    cache: new InMemoryCache()
});

class App extends Component {
  render() {
        if (this.props.query && this.props.query.loading) {
            return <div>Loading...</div>
        }

        if (this.props.query && this.props.query.error) {
            return <div>Error: {this.props.query.error.message}</div>
        }

        const person = this.props.query.me;
        return <div> {person.name} </div>
  }
}

const personQuery = gql`
    query PersonQuery {
        me {
            name
        }
    }
`;
App = graphql(personQuery, { name: 'query' })(App);

ReactDOM.render(
    <ApolloProvider client={client}>
        < App />
    </ApolloProvider>
    , document.getElementById('root')
);

【问题讨论】:

    标签: graphql apollo react-apollo apollo-client


    【解决方案1】:

    更新:我可以使用来自 react-apollo/test-utils 的 MockedProvider 让事情正常工作,但我想知道这是否是最好的前进方式。例如,据我所知,使用 MockedProvider 要求您为组件可能执行的每个查询设置完全匹配,而来自 graphql-toolsaddMockFunctionsToSchema 将让您更灵活地自定义模拟,如 the docs 所示 - - 我只是希望我能做到这一点。

    这是使用 MockedProvider 的更新后的 index.js 文件示例:

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    
    import { ApolloProvider } from 'react-apollo';
    import { ApolloClient } from 'apollo-client';
    import { SchemaLink } from "apollo-link-schema";
    import { InMemoryCache } from 'apollo-cache-inmemory';
    import { ApolloCache } from 'apollo-cache';
    
    import gql from 'graphql-tag';
    import { graphql } from 'react-apollo';
    
    import { MockedProvider } from 'react-apollo/test-utils';
    
    import { makeExecutableSchema, addMockFunctionsToSchema, MockList } from 'graphql-tools';
    const typeDefs = `
    type Query {
      me: Person!
    }
    
    type Person {
        name: String!
    }
    `;
    const schema = makeExecutableSchema({ typeDefs });
    addMockFunctionsToSchema({ schema });
    
    const schemaLink = new SchemaLink(schema);
    const client = new ApolloClient({
        link: schemaLink,
        cache: new InMemoryCache()
    });
    
    class App extends Component {
      render() {
            if (this.props.query && this.props.query.loading) {
                return <div>Loading...</div>
            }
    
            if (this.props.query && this.props.query.error) {
                return <div>Error: {this.props.query.error.message}</div>
            }
    
            const person = this.props.query.me;
            return <div> {person.name} </div>
      }
    }
    
    const personQuery = gql`
        query PersonQuery {
            me {
                __typename
                name
            }
        }
    `;
    const personQueryMockedData = {
        me: {
            __typename: 'String',
            name: 'Gabe'
        }
    }
    
    
    App = graphql(personQuery, { name: 'query' })(App);
    
    ReactDOM.render(
        <MockedProvider mocks={
            [
                { 
                    request: { query: personQuery, variables: { cache: false } },
                    result: { data: personQueryMockedData }
                }
            ]
        }>
            < App />
        </MockedProvider>
        , document.getElementById('root')
    );
    

    【讨论】:

      【解决方案2】:

      我认为链接需要是别的东西

      试试这个

      import { ApolloLink, Observable } from 'apollo-link';
      
      // ...
      const link = new ApolloLink(operation => {
        const { query, operationName, variables } = operation;
        return new Observable(observer =>
          graphql(schema, print(query), null, null, variables, operationName)
            .then(result => {
              observer.next(result);
              observer.complete();
            })
            .catch(observer.error.bind(observer))
        );
      });
      

      在代码上下文中

      import React, { Component } from 'react';
      import ReactDOM from 'react-dom';
      
      import { ApolloLink, Observable } from 'apollo-link';
      import { ApolloProvider } from 'react-apollo';
      import { ApolloClient } from 'apollo-client';
      import { SchemaLink } from "apollo-link-schema";
      import { InMemoryCache } from 'apollo-cache-inmemory';
      import { ApolloCache } from 'apollo-cache';
      
      import gql from 'graphql-tag';
      import { graphql } from 'react-apollo';
      
      import { makeExecutableSchema, addMockFunctionsToSchema, MockList } from 'graphql-tools';
      const typeDefs = `
      type Query {
        me: Person!
      }
      
      type Person {
          name: String!
      }
      `;
      const schema = makeExecutableSchema({ typeDefs });
      addMockFunctionsToSchema({ schema });
      
      const link = new ApolloLink(operation => {
        const { query, operationName, variables } = operation;
        return new Observable(observer =>
          graphql(schema, print(query), null, null, variables, operationName)
            .then(result => {
              observer.next(result);
              observer.complete();
            })
            .catch(observer.error.bind(observer))
        );
      });
      const client = new ApolloClient({
        link,
        cache: new InMemoryCache()
      });
      
      class App extends Component {
        render() {
          if (this.props.query && this.props.query.loading) {
            return <div>Loading...</div>
          }
      
          if (this.props.query && this.props.query.error) {
            return <div>Error: {this.props.query.error.message}</div>
          }
      
          const person = this.props.query.me;
          return <div> {person.name} </div>
        }
      }
      
      const personQuery = gql`
          query PersonQuery {
              me {
                  name
              }
          }
      `;
      console.log(personQuery)
      App = graphql(personQuery, { name: 'query' })(App);
      
      ReactDOM.render(
        <ApolloProvider client={client}>
          < App />
        </ApolloProvider>
        , document.getElementById('root')
      );
      

      【讨论】:

        猜你喜欢
        • 2019-06-22
        • 2021-05-17
        • 2020-04-11
        • 2021-04-20
        • 2021-06-01
        • 2018-04-19
        • 2016-08-31
        • 2020-11-19
        • 2017-09-08
        相关资源
        最近更新 更多