在 GraphQL 查询中传递自定义变量
Posted
技术标签:
【中文标题】在 GraphQL 查询中传递自定义变量【英文标题】:Pass Custom Variables In GraphQL Query 【发布时间】:2020-07-09 07:16:09 【问题描述】:我有一个UpdateUserPage
,它可以根据传递的输入变量的数量以不同的方式调用突变,例如:
只更新名字
mutation
updateUser(email: "d@d.com",
input: firstName:"check")id
名字和姓氏都更新了:
mutation
updateUser(email: "d@d.com",
input: firstName:"check", lastName: "new")id
现在在我的代码中查询:
export const UPDATE_USER = gql`
mutation UpdateUser($email: String!, $firstName: String, $lastName: String)
updateUser(
email: $email
input: firstName: $firstName, lastName: $lastName
)
id
firstName
`;
我想要什么:
我想更改我的表单,如果用户只输入名字并将姓氏字段留空, 那么只有 firstName 应该被更新,这意味着应该使用第一种类型的查询,而 lastName 应该保持在调用突变之前的状态。
现在发生了什么:
例如,以前 firstName 是 HELLO,lastName 是 WORLD。现在,我将 firstName 更新为 CHECK 并将 lastName 选项留空。因此,当它返回值时,它应该将 CHECK 作为 firstName 返回,将未修改的 WORLD 作为 lastName 返回。但是,现在,它显示 lastName 为未定义。 如果我检查资源,我会看到:
"operationName":"UpdateUser","variables":"email":"c@c.com","firstName":"Final","query":"mutation UpdateUser($email: String!, $firstName: String, $lastName: String) \n updateUser(email: $email, input: firstName: $firstName, lastName: $lastName) \n id\n firstName\n __typename\n \n\n" Looks like the lastName is still being passed in the mutation.
这意味着 lastName 仍在突变中使用。所以,我需要一种将自定义变量传递到我的查询中的方法:
$input : Object!
不起作用。
这是我整个页面的代码:
export default function UpdateUserPage()
const [isSubmitted, setIsSubmitted] = useState(false);
const [isUpdated, setIsUpdated] = useState(false);
const [updateUser] = useMutation(UPDATE_USER);
let submitForm = (
email: string,
firstName: string,
lastName: string,
) =>
setIsSubmitted(true);
if (email && (firstName || lastName || phoneNumber))
const vars:any =
email
;
if( firstName !== '')
vars.firstName = firstName
if( lastName !== '')
vars.lastName = lastName
updateUser(
variables: vars)
.then(( data : any) =>
setIsUpdated(true);
console.log(updateUser);
console.log('FN: ', data.updateUser.firstName);
console.log('LN: ', data.updateUser.lastName);
)
.catch((error: message: string ) =>
setIsUpdated(false);
);
;
return (
<div>
<Formik
initialValues=
firstName: '',
lastName: '',
email: '',
phoneNumber: '',
onSubmit=(values, actions) =>
setTimeout(() =>
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
, 1000);
validationSchema=schema>
props =>
const
values: firstName, lastName, email, phoneNumber ,
errors,
touched,
handleChange,
isValid,
setFieldTouched,
= props;
const change = (name: string, e: FormEvent) =>
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
;
return (
<div className="main-content">
<form
style= width: '100%'
onSubmit=e =>
e.preventDefault();
submitForm(email, firstName, lastName);
>
<div>
<TextField
variant="outlined"
margin="normal"
id="email"
name="email"
helperText=touched.email ? errors.email : ''
error=touched.email && Boolean(errors.email)
label="Email"
value=email
onChange=change.bind(null, 'email')
/>
<br></br>
<TextField
variant="outlined"
margin="normal"
id="firstName"
name="firstName"
helperText=touched.firstName ? errors.firstName : ''
error=touched.firstName && Boolean(errors.firstName)
label="First Name"
value=firstName
onChange=change.bind(null, 'firstName')
/>
<br></br>
<TextField
variant="outlined"
margin="normal"
id="lastName"
name="lastName"
helperText=touched.lastName ? errors.lastName : ''
error=touched.lastName && Boolean(errors.lastName)
label="Last Name"
value=lastName
onChange=change.bind(null, 'lastName')
/>
<CustomButton
text='Update User Info'
/>
</div>
</form>
</div>
);
</Formik>
</div>
);
编辑:
来自架构:
input: UpdateUserInput!
input UpdateUserInput
email: String
firstName: String
lastName: String
phoneNumber: String
现在,我已经做到了:
interface UpdateUserInput
email: String
firstName: String
lastName: String
phoneNumber: String
export const UPDATE_USER = gql`
mutation UpdateUser($email: String!, $input : UpdateUserInput)
updateUser(
email: $email
input: $input
)
id
firstName
`;
但是,当我提交表单时,我仍然收到此错误:
GraphQL error: The variable `input` type is not compatible with the type of the argument `input`.
Expected type: `UpdateUserInput`.
可能是因为我仍然从我的主要UpdateUserPage
传递vars
。我该如何改变呢?
【问题讨论】:
【参考方案1】:$input
变量的类型可以是 updateUser
上的 input
参数的类型。如果您不是自己编写 GraphQL 架构,则需要检查您的 API 文档或 GraphiQL/GraphQL Playground 接口以确定要使用的类型。
对每个字段使用单个变量 ($input
) 而不是多个变量($firstName
和 $lastName
)是首选的处理方式。也就是说,您的查询没有任何问题。您当前的查询:
mutation ($email: String!, $firstName: String, $lastName: String)
updateUser(
email: $email
input: firstName: $firstName, lastName: $lastName
)
id
使用变量"email": "c@c.com", "firstName": "Final"
将等价于到
mutation ($email: String!, $input: WhateverYourInputTypeIs)
updateUser(
email: $email
input: $input
)
id
"email": "c@c.com", "input": "firstName": "Final"
。
在这两种情况下,传递给服务器端解析器的参数都是相同的。如果您在突变运行后得到错误的 lastName
值,那么这就是解析器如何处理它接收到的参数的问题。
【讨论】:
感谢您为我指明正确的方向!我现在理解了类型。但是,我在我的代码中正确定义它时遇到问题?你能看到我的问题中的编辑吗?可能是一些小错误。 参数不可为空,因此您需要确保您的变量也是如此(即在类型上附加一个!
)。【参考方案2】:
您可能需要修改您的界面,以便不需要这些字段。
interface UpdateUserInput
email?: String
firstName?: String
lastName?: String
phoneNumber?: String
通过在字段中添加问号,您可以将它们设为可选,以便您一次可以传递一个或多个。
【讨论】:
以上是关于在 GraphQL 查询中传递自定义变量的主要内容,如果未能解决你的问题,请参考以下文章