#typescript #graphql #apollo-client
#typescript #graphql #apollo-клиент
Вопрос:
У меня есть мутация, которая запускается при onClick. Эта мутация принимает одну необязательную переменную. Эта переменная поступает из запроса.
Поскольку запрос может завершиться ошибкой, переменная может быть неопределенной, и typescript жалуется. Таким образом, мой вопрос: как я могу пропустить мутацию, если переменная не определена?
const { data: myQueryData } = useQuery(GET_MY_QUERY_DATA, {
variables: {
firstVariable: 100
}
})
const myVariable = myQueryData?.getMyQueryData <-- This is "number" | "undefined"
const [updateMutation] = useMutation(
UPDATE_STUFF
)
updateMutation({
variables: {
myVariable <-- This, as before, can be "number" | "undefined"
BUT it cannot be undefined since it is NOT optional
}
})
Комментарии:
1.
if(myVariable) updateMutation
2. Спасибо, я это сделал. Я хотел бы знать, есть ли другой способ. Что, если мне нужна не 1 переменная, а 10? Должен ли я использовать много
amp;amp;
, чтобы проверить, присутствуют ли они?3.
const myVariable = myQueryData ? myQueryData.getMyQueryData : 0;
4. …
if(myQueryData)
может быть достаточно хорошим (как условие) для многих данных, полученных из результата запроса [возможно, с ошибкой]5. Проблема с этим подходом
myQueryData ? myQueryData.getMyQueryData : 0;
заключается в том, что я не хочу, чтобы это было0
в случае сбоя. Я хочу, чтобы мутация не выполнялась
Ответ №1:
Проблема вызвана Реакцией. Поскольку мы не можем условно вызывать хуки, мы всегда должны вызывать их в одном и том же порядке.
useQuery
выполняет запрос немедленно. По этой причине skip
был включен флаг для управления, должен ли он выполняться или нет (API запросов).
useQuery(Foo, { skip: true })
useMutation
у него нет такой опции (Mutation API). Мутации работают немного по-другому в том смысле, что их выполнение отличается до тех пор, пока не будет вызван обратный вызов. Но, к счастью, обратный вызов не является перехватом и может быть вызван условно. Таким образом, решение состоит в том, чтобы условно назвать его.
const [runMutation] = useMutation(MyMutation)
if (...) {
await runMutation()
}
const myVariable = myQueryData?.getMyQueryData
if (myVariable) {
updateMutation({
variables: {
myVariable
}
})
}
Я столкнулся с этой проблемой, поскольку хотел сгенерировать мутации graphql для диапазона идентификаторов.
const MyMutation = gql`
mutation MyMutation {
${inputIds.map((id) => `cancelEntity(id: "${id}")`).join('n')}
}
`
Но если входной массив пуст, это создает ошибку DocumentNode
.
Итак, я попытался условно сгенерировать мутацию, возвращающую пустой DocumentNode.
Не удалось проанализировать пустой ввод
const Mutation = gql``
Не удалось проанализировать комментарии
const Mutation = gql`
# noop
`
Не удалось проанализировать пустую мутацию: неожиданный EOF
const Mutation = gql`
mutation Foo {
# noop
}
`
Я попытался сгенерировать noop DocumentNode для передачи в useMutation
. Но это не удалось, поскольку он распознает, что это не запрос, мутация или подписка.
const Mutation: DocumentNode = {
kind: 'Document',
definitions: [
{
kind: 'FragmentDefinition',
name: { kind: 'Name', value: 'noop' },
typeCondition: {
kind: 'NamedType',
name: { kind: 'Name', value: 'noop' },
},
selectionSet: { kind: 'SelectionSet', selections: [] },
},
],
}
Жаль, что я не смог сгенерировать допустимую пустую мутацию. Потому что мы упаковываем эту мутацию в ее собственный хук и возвращаем обратный вызов мутации. Это означает, что многие компоненты могут использовать этот хук и вызывать мутацию. Все они теперь отвечают за условный вызов мутации.
const { cancelEntity } = useCancelEntity(inputIds)
if (inputIds amp;amp; inputIds.length > 1) {
await cancelEntity()
}
Мы могли бы упаковать мутации в одну мутацию и вызывать ее много раз.
await Promise.all([cancelEntity('1'), cancelEntity('2')])
Это создает более чистый код, но заставляет нас делать много сетевых запросов.