在 GraphQL 查询中传递自定义变量
Pass Custom Variables In GraphQL Query
我有一个 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 应该更新,这意味着应该使用第一种类型的查询,而 lastName 应该保持在调用 mutation 之前的状态。
现在发生了什么:
例如,以前的名字是 HELLO,姓氏是 WORLD。现在,我将 firstName 更新为 CHECK 并将 lastName 选项留空。所以当它 returns 值时,它应该 return 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`.
可能是因为我仍在通过 vars
从我的主要 UpdateUserPage
。我该如何改变它?
$input
变量的类型可以是 updateUser
上 input
参数的类型。如果您没有自己编写 GraphQL 架构,则需要查看 API 的文档或 GraphiQL/GraphQL 游乐场界面以确定要使用的类型。
对每个字段($firstName
和 $lastName
)使用单个变量 ($input
) 而不是多个变量是首选的处理方式。也就是说,您的查询没有任何问题。您当前查询:
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
值,那么这是解析器如何处理它接收到的参数的问题。
您可能需要修改您的界面,以便不需要这些字段。
interface UpdateUserInput {
email?: String
firstName?: String
lastName?: String
phoneNumber?: String
}
通过向字段添加问号,您可以将它们设为可选,这样您就可以一次传递一个或多个。
我有一个 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 应该更新,这意味着应该使用第一种类型的查询,而 lastName 应该保持在调用 mutation 之前的状态。
现在发生了什么:
例如,以前的名字是 HELLO,姓氏是 WORLD。现在,我将 firstName 更新为 CHECK 并将 lastName 选项留空。所以当它 returns 值时,它应该 return 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`.
可能是因为我仍在通过 vars
从我的主要 UpdateUserPage
。我该如何改变它?
$input
变量的类型可以是 updateUser
上 input
参数的类型。如果您没有自己编写 GraphQL 架构,则需要查看 API 的文档或 GraphiQL/GraphQL 游乐场界面以确定要使用的类型。
对每个字段($firstName
和 $lastName
)使用单个变量 ($input
) 而不是多个变量是首选的处理方式。也就是说,您的查询没有任何问题。您当前查询:
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
值,那么这是解析器如何处理它接收到的参数的问题。
您可能需要修改您的界面,以便不需要这些字段。
interface UpdateUserInput {
email?: String
firstName?: String
lastName?: String
phoneNumber?: String
}
通过向字段添加问号,您可以将它们设为可选,这样您就可以一次传递一个或多个。