web-dev-qa-db-ja.com

突然変異を行うときに「null不可フィールドにnullを返すことができません」というエラーが表示されるのはなぜですか?

私はサーバー側で(Apollo)GraphQLを試しており、おそらくばかげた問題を抱えています。ユーザーをサインアップしようとしていますが、下のリンク画像に示されているエラーが発生し続けます。何が問題ですか? GraphQlをテストしているだけなので、非常に単純な認証フローは無視してください。

enter image description here

関連するコードスニペットを次に示します。

スキーマ

export default `

type User {
    id: ID!
    name: String!
    email: String!
}

type Query {
    allUsers: [User]
  currentUser: User
}

type Mutation {
    createAccount(name: String!, email: String!, password: String!): User
    loginUser(email: String!, password: String!): User
    updatePassword(email: String!, password: String!, newPassword: String!): User
    deleteAccount(email: String!, password: String!): User
}

`

リゾルバ

createAccount: async (
  parent,
  { name, email, password },
  { User },
  info
) => {
  try {
    // Check for invalid (undefined) credentials
    if (!name || !email || !password) {
      return 'Please provide valid credentials';
    }

    // Check if there is a user with the same email
    const foundUser = await User.findOne({ email });

    if (foundUser) {
      return 'Email is already in use';
    }

    // If no user with email create a new user
    const hashedPassword = await bcrypt.hash(password, 10);
    await User.insert({ name, email, password: hashedPassword });

    const savedUser = await User.findOne({ email });

    return savedUser;
  } catch (error) {
    return error.message;
  }
},
5
Collins Orlando

リゾルバの最大の問題は、任意の数のシナリオで、Userオブジェクトを返す代わりに、文字列を返すことです。スキーマでは、createAccountUserまたはnullUser!、null不可であり、nullも有効なタイプではありません)。

リゾルバで文字列を返すと、オブジェクトを想定しているため、1つに強制され、そのオブジェクトのUserプロパティ(nameemailなど)の検索を開始します)。これらのプロパティは存在せず、Userオブジェクトのnull以外のプロパティであるため、null/undefinedを返すとエラーになります。

リゾルバは、おそらく、必要なエラーをスローする必要があります。次に、応答のerrors配列の一部として返されます。例えば:

// Check if there is a user with the same email
const foundUser = await User.findOne({ email })

if (foundUser) throw new Error('Email is already in use')

// If no user with email create a new user
const hashedPassword = await bcrypt.hash(password, 10);
await User.insert({ name, email, password: hashedPassword });

const savedUser = await User.findOne({ email });

return savedUser;

重複した電子メールがある場合、応答は次のようになります。

{
  "data": {
    "createAccount": null
  },
  "errors": [
    {
      "message": "Email is already in use",
      "locations": [
        {
          "line": 4,
          "column": 3
        }
      ],
      "path": [
        "createAccount"
      ]
    }
  ]
}

クライアントでのエラーの表示方法を操作する場合は、ApolloサーバーミドルウェアのformatErrorまたはformatResponse構成オプションを利用する必要があります。また、カスタムエラーを使用することをお勧めします。これにより、codeなどのカスタムプロパティを追加して、クライアント側でエラータイプをより簡単に識別できます。

最後に、名前、電子メール、またはパスワードがリゾルバー内で定義されているかどうかを確認する必要はありません-スキーマにはすでにこれらの入力がnull以外としてマークされています。

9
Daniel Rearden