【问题标题】:how to use enum in apollo-client?如何在 apollo-client 中使用枚举?
【发布时间】:2020-01-19 17:32:47
【问题描述】:

OrderTypesEnum.gql 中定义的枚举

enum OrderTypes {
  full_buy
  pink_buy
}

导入 OrderTypesEnum.gql 文件

import OrderTypes from '@/graphql/OrderTypesEnum.gql'`

但是,如何在代码中获取枚举?

我使用OrderTypes.full_buy得到一些错误:

   self.$apollo.mutate({
        mutation: createOrder,
        variables: {
          subjectId: self.subject.id,
          types: OrderTypes.full_buy
        }
      })
Mutation createOrderMutation error: Invariant Violation: Schema type definitions not allowed in queries. Found: "EnumTypeDefinition"

OrderTypes 类型枚举的检查

【问题讨论】:

    标签: graphql apollo apollo-client vue-apollo


    【解决方案1】:

    正如错误消息提示的那样,Schema type definitions not allowed in queries.,您不能在操作文档 (ExecutableDefinition) 中添加枚举定义。您只能拥有操作(查询、变异或订阅)或片段定义。也就是说,这是无效的:

    enum OrderTypes {
      FULL_BUY
      PINK_BUY
    }
    
    mutation createOrderMutation {
      ...
    }
    

    如果你想在你的客户端定义一个本地枚举,你可以在ApolloClient初始化时使用typeDefs属性:

    const client = new ApolloClient({
      cache,
      typeDefs: gql`
        enum OrderTypes {
          FULL_BUY,
          PINK_BUY
        }
      `,
    });
    

    然后您将能够在 客户端 内省(即 Apollo 扩展)上看到 OrderTypes 枚举。

    注意客户端的亮点:如果您尝试使用此枚举为非客户端字段发送请求(即没有@client 指令)并且它通过您的服务器进行,​​您将收到架构错误表示枚举类型不存在,除非您在后端定义它。

    【讨论】:

    • 值得注意的是,客户端 typeDef 是only used for introspection, not validation。无需添加任何 typeDef 即可使用本地状态。
    • 如何在 args 中设置 FULL_BUY 枚举?如何访问OrderTypes => FULL_BUY
    • 好电话,丹尼尔。 OP 问题:如果您调用的突变在服务器中正确定义了 OrderTypes 类型的参数,您可以直接使用枚举值并且它会起作用。例如 createOrderMutation(arg: FULL_BUY)。
    • 但是有些时间需要通过变量而不是直接。
    • 这对我不起作用。正如丹尼尔所说,typeDef 不会为验证添加任何值。即使我设置了这些值,有没有办法在 gql 查询本身中使用它们?
    【解决方案2】:

    现在我遇到了同样的问题。我找到了这样的解决方案。也许它可以解决您的问题。

    import { Component, OnInit } from '@angular/core';
    import { MatSnackBar } from '@angular/material';
    import { Router } from '@angular/router';
    import { slugify } from '../../helpers/slugify';
    import { SEOService } from '../../services/seo.service';
    
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import { MustMatch } from '../../helpers/must-match-validator';
    
    import { MAT_MOMENT_DATE_FORMATS, MomentDateAdapter } from '@angular/material-moment-adapter';
    import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
    
    import { CreateUserInput, RegisterPageRegisterGQL, Roles } from '@generated-types';
    
    @Component({
      selector: 'app-register',
      templateUrl: './register.component.html',
      styleUrls: [
        './register.component.scss'
      ],
      providers: [
        // The locale would typically be provided on the root module of your application. We do it at
        // the component level here, due to limitations of our example generation script.
        { provide: MAT_DATE_LOCALE, useValue: 'tr-TR' },
    
        // `MomentDateAdapter` and `MAT_MOMENT_DATE_FORMATS` can be automatically provided by importing
        // `MatMomentDateModule` in your applications root module. We provide it at the component level
        // here, due to limitations of our example generation script.
        { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
        { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
      ],
    })
    
    export class RegisterComponent implements OnInit {
      registerForm: FormGroup;
      submitted = false;
      error: any;
      genders: any = ['Kadın', 'Erkek', 'Belirtmek İstemiyorum'];
    
      user: CreateUserInput;
    
      constructor(
        public snackBar: MatSnackBar,
        private router: Router,
        private seoService: SEOService,
        private formBuilder: FormBuilder,
        private _adapter: DateAdapter<any>,
        private registerPageRegisterGQL: RegisterPageRegisterGQL,
      ) { }
    
      // convenience getter for easy access to form fields
      get f() { return this.registerForm.controls; }
    
      ngOnInit() {
        // datepicker locale
        this._adapter.setLocale('tr');
        // seo service
        this.seoService.addDefaultMetaTags();
        this.seoService.meta.updateTag({ name: 'robots', content: 'noindex' });
        this.seoService.addTitle('Kayıt Ol | kitaphub');
        // form validator
        this.registerForm = this.formBuilder.group({
          userName: ['', Validators.required],
          email: ['', [Validators.required, Validators.email]],
          firstName: ['', Validators.required],
          lastName: ['', Validators.required],
          password: ['', [Validators.required, Validators.minLength(6)]],
          confirmPassword: ['', Validators.required],
          gender: ['', Validators.required],
          dateOfBirth: ['', Validators.required],
          acceptTerms: [false, Validators.requiredTrue]
        }, {
          validator: MustMatch('password', 'confirmPassword')
        });
      }
    
      async onSubmit() {
        console.log('onSubmit');
        this.submitted = true;
    
        // stop here if form is invalid
        if (this.registerForm.invalid) {
          return;
        }
    
        // display form values on success
        alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.registerForm.value, null, 4));
    
        this.registerPageRegisterGQL.mutate({
          user: {
            userName: this.registerForm.value.userName,
            email: this.registerForm.value.email,
            slug: slugify(this.registerForm.value.userName),
            firstName: this.registerForm.value.firstName,
            lastName: this.registerForm.value.lastName,
            password: this.registerForm.value.password,
            gender: this.registerForm.value.gender,
            role: Roles.MEMBER
          }
        }).subscribe(({ data }) => {
          console.log('got data:', data);
          this.openSnackBar('KAYIT İŞLEMİ TAMAMLANDI');
        }, (error: any) => {
          this.handleError(error);
          console.log('there was an error sending', error);
        });
      }
    
      onReset() {
        this.submitted = false;
        this.registerForm.reset();
      }
    
      handleError(error: any) {
        this.error = error.message;
      }
    
      openSnackBar(text: string) {
        return this.snackBar.open(text, 'X', { horizontalPosition: 'right', verticalPosition: 'top', duration: 3000 });
      }
    
    }
    
    

    【讨论】:

      【解决方案3】:

      先决条件:

      我们必须在我们的 GraphQL 架构中定义 (服务器端,不需要客户端配置)

      假设我们已经定义了:

      enum SomeEnumType {
          OPTION1,
          OPTION2,
          OPTION3
      }
      

      我们还必须以适当的方式配置我们的 Apollo 客户端,并将其与 GraphQL API 连接。

      然后在客户端:

      export const OUR_MUTATION = gql`
          mutation ourMutation($foo: SomeEnumType){
              ourMutation(foo: $foo){
                  bar
              }
          }    
      `
      

      只有这样做,您才能在查询或突变中将枚举作为变量传递。例如使用 useMutation 钩子,我们现在可以进行如下变异:

      const [ourMutation] = useMutation(OUR_MUTATION, {
              variables: {
                  foo: "OPTION2"
              },
      

      由于 gql 标签中的类型定义与 Schema 中的定义相同,GraphQL 将我们的变量识别为枚举类型,尽管我们将其作为字符串给出。

      如果我们想使用 typescript 枚举将枚举传递给我们的变量,我们可以这样做:

      enum SomeEnumType {
          OPTION1 = 0,
          OPTION2 = 1,
          OPTION3 = 2
      }
      
      const [ourMutation] = useMutation(OUR_MUTATION, {
              variables: {
                  foo: SomeEnumType[SomeEnumType.OPTION1]
              },
      
      

      【讨论】:

        猜你喜欢
        • 2021-07-29
        • 2019-10-26
        • 2022-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-05
        • 2010-09-26
        • 2013-02-11
        相关资源
        最近更新 更多