Пропустить мутацию, если одна переменная не определена

#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')])
  

Это создает более чистый код, но заставляет нас делать много сетевых запросов.