【问题标题】:GraphQL Cannot return null for non-nullable field User.createdAtGraphQL 无法为不可为空的字段 User.createdAt 返回 null
【发布时间】:2021-10-24 01:15:18
【问题描述】:
@Mutation (() => UserResponse)
    async register(
        @Arg('options', () => UsernamePasswordInput ) options: UsernamePasswordInput,
        @Ctx() {em, req}: MyContext
    ): Promise<UserResponse>{

        const errors = validateRegister(options);
 

        
        const hashedPassword = await argon2.hash(options.password)
        let user;
     
        try{
            /* cast to this type, em as entity manager  */
          
            const result = await (em as EntityManager).createQueryBuilder(User).getKnexQuery().insert({
                username: options.username,
                password: hashedPassword,
                email: options.email,
                created_at: new Date(),
                updated_at: new Date()
            }).returning("*");
            /* returns all fields back from the user  */
            user  = result[0];

        } catch(err: any ) {
            if (err.code === '23505' || err.detail.includes("already exists")){
                // duplicate name
                /* returning errors object */
               return {
                   errors: [{
                       field: 'username or email',
                       message: 'that username or email already exists'
                   }]
               }
            }    
            
        }
        req.session.userId = user.id;
        return {user};
    }
import { Entity, PrimaryKey, Property } from "@mikro-orm/core";
import { Field, Int, ObjectType } from "type-graphql";

@ObjectType() 
@Entity()
export class User {
  @Field(() => Int) 
  @PrimaryKey()
  id!: number;

  @Field(() => String )
  @Property({type: "date", default: "Now()", nullable: true})
  createdAt = new Date();

  @Field(() => String )
  @Property({type: "date",onUpdate: () => new Date()})
  updatedAt = new Date();

  @Field(() => String)
  @Property({type: 'text', unique: true}) 
  username!: string;

  @Field(() => String)
  @Property({type: "text", unique: true})
  email!: string;
  /* this password has no graphql endpoint field */
  @Property({type: 'text'}) 
  password!: string;

}
const Register: React.FC<registerProps> = ({}) => {
     const router = useRouter();
     const [, register] = useRegisterMutation();
     return (
        <Wrapper variant = "small">
            <Formik 
                initialValues = {{email: "", username: "", password: ""}}
                onSubmit = {
                    
                    async (values, {setErrors}) => { 
                        /* this is  a promise retruned therefore just return */

                         /* maps to the graphql mutation specified above */
                    
                         const response = await register({options: values});
                         console.log("user: ", response)
                         /* code gen is detecting the types of this response from graphql */

                         /* check if the errors object has any errors */
                         if (response.data?.register.errors){
                           
                            /* map then into a key:value pair for use in the formik set errors to nicely display the errors */
                            setErrors(toErrorMap(response.data.register.errors));
                         } else if(response.data?.register.user){
                             // worked

                             /* use next js hook to return to homepage  */
                             router.push('/');
                         }
                         
                    }}>

                {/* 
                    this is a render prop, we are taking values state and handleChange function from Formik , and passing our logic in
                    using the handles they gave us.
                */}
                {({isSubmitting}) => (
                   <Form>
                       <InputField 
                            name = "username" 
                            placeholder = "username" 
                            label = "Username" 
                       />
                        <Box mt = {4}>
                            <InputField 
                                name = "email" 
                                placeholder = "email" 
                                label = "Email" 
                            />
                       </Box>
                       <Box mt = {4}>
                            <InputField 
                                name = "password" 
                                placeholder = "password" 
                                label = "Password" 
                                type = "password"
                            />
                       </Box>
                       <Button 
                            _hover = {{
                                backgroundColor: "purple", 
                                color: "white",
                            }}
                            ml = "auto"
                            mr = "auto"
                            mt = {4}
                            display = "block"
                            type = "submit"
                            backgroundColor = "black"
                            /* this loads whenever we are submittting, a cool loading symbol */
                            isLoading = {isSubmitting}
                        > 
                         register
                        </Button>
                    </Form>
                )}  
            </Formik>
        </Wrapper>
    )
}

export default withUrqlClient(createUrqlClient, {ssr: true})(Register);

当我通过电子邮件/密码/用户名注册时在我的页面上 它从graphql返回这个错误

{
    "errors": [
        {
            "message": "Cannot return null for non-nullable field User.createdAt.",
            "locations": [
                {
                    "line": 10,
                    "column": 7
                }
            ],
            "path": [
                "register",
                "user",
                "createdAt"
            ],
            "extensions": {
                "code": "INTERNAL_SERVER_ERROR",
                "exception": {
                    "stacktrace": [
                        "Error: Cannot return null for non-nullable field User.createdAt.",
                        "    at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:559:13)",
                        "    at resolveField (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:472:19)",
                        "    at executeFields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:292:18)",
                        "    at collectAndExecuteSubfields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:748:10)",
                        "    at completeObjectValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:738:10)",
                        "    at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:590:12)",
                        "    at resolveField (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:472:19)",
                        "    at executeFields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:292:18)",
                        "    at collectAndExecuteSubfields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:748:10)",
                        "    at completeObjectValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:738:10)",
                        "    at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:590:12)",
                        "    at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:556:21)",
                        "    at D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:469:16",
                        "    at processTicksAndRejections (node:internal/process/task_queues:96:5)",
                        "    at async execute (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:205:20)",
                        "    at async Object.processGraphQLRequest (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:139:28)"
                    ]
                }
            }
        }
    ],
    "data": {
        "register": {
            "errors": null,
            "user": null
        }
    }
}

发生这种情况的原因不明,我真的不知道该说什么了

............. ... . . . . . ..................................................... ..................................................... ..................................................... ......

【问题讨论】:

    标签: reactjs typescript graphql


    【解决方案1】:

    当设置为不可为空的字段从服务器返回为空时,通常会发生这种情况。

    请检查从服务器返回的对象,并验证您根据设置标记的所有字段是否都返回了某个值。

    一种快速检查的方法是全部设为{ nullable: true } 并查看是否有效,然后您可以查看哪个是违规者。

    【讨论】:

    • 是的,我现在已经解决了这个问题。基本上我所有的逻辑都是正确的,graphql 等等。但我的 ORM 生成的名称与我的模式定义不同。它在迁移中变成了 variableName > variable_name。因此,正如您提到的,我的 Graphql 查询针对的是错误的字段,这当然会导致空字段问题。 mikroORM 需要解决这个问题。
    • 好的,很好。很高兴它有帮助。如果有帮助,请接受答案。
    猜你喜欢
    • 2021-11-27
    • 2021-10-29
    • 2021-03-18
    • 2022-01-02
    • 2019-10-04
    • 2019-10-25
    • 2019-07-08
    • 2018-04-10
    • 2019-05-28
    相关资源
    最近更新 更多