Как отправить запрос API из внешнего интерфейса на основе результата предыдущего запроса API на сервере Apollo graphql?

Я работаю с двумя конечными точками API. Первый возвращает список дат в строковом формате, для которых доступны данные. Затем дату можно добавить ко второй конечной точке и отобразить дополнительные данные. На игровой площадке Graphql мне удалось заставить все это работать. Во внешнем интерфейсе у меня есть раскрывающийся список выбора для дат, но я не смог запустить второй вызов API, когда я нажимаю на любую дату. Это первый раз, когда я использую мутацию graphql, и мне не удалось получить второй запрос API для возврата каких-либо данных при выборе даты. Спасибо.

Интерфейсный код:

app.tsx


import * as React from 'react'
import { useState } from 'react'
import { useMutation } from '@apollo/react-hooks'
import { IrriSatQuery } from '../../generated/graphql'
import { MAP_LAYER } from './query'

interface Props {
  data: IrriSatQuery;
}

const IrriSat: React.FC<Props> = ({ data }) => {
  const [option, setOption] = useState((data?.mapDates as any)[0].date!)
  const [getLayer] = useMutation(MAP_LAYER)

  return (
    <>

    <ContentWrapper>
      <select value={option} onChange={( e: React.ChangeEvent<HTMLSelectElement>, ): void => {setOption(e.target.value, getLayer(e.target.value)}} onSelect={() => getLayer({variables: {type: option}})}>
        {data?.mapDates?.slice(0,52).map(res => 
          <option key={res?.date!} value={res?.date!}>{res?.date}</option>
          )
        }
      </select>
    </ContentWrapper>
    </>
  )
}

export default IrriSat

query.ts


export const QUERY_IRR_SAT = gql`
 query IrriSat {
   mapDates {
     date
     dateurl
   }
 }
`

export const MAP_LAYER = gql`
  mutation MapLayer($date: String!) {
     mapDate(date: $date) {
       token
       mapid
       name
     }

   }
`

Внутренний код:

сервер.js

class IrriSatAPI extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = 'https://irrisat-cloud.appspot.com/_ah/api/irrisat/v1/services/'
  }

  async getMapsDates() {
    const response = await this.get('maps/dates')
    return Array.isArray(response.items) ? response.items.map(response => this.mapsDatesReducer(response)) : []
  }

  mapsDatesReducer(response) {
    return {
      date: response.date,
      dateurl: response.dateurl,
    }
  }

  async getMapsLayer(date) {

    const response = await this.get(`maps/layers/${date}`)
    return Array.isArray(response.items) ? response.items.map(response => this.mapsLayerReducer(response)) : []
  }

  mapsLayerReducer(response) {
    return {
      token: response.token,
      mapid: response.mapid,
      name: response.name
    }
  }


  }
}

схема.js

  type MapDates {
    date: String
    dateurl: String
  }

  type Mutation {
    mapDate(date: String): [MapsLayers]
  }

  type Query {
    mapDates: [MapDates]

resolver.js

module.exports = {
  Query: {
    mapDates: (_, __, { dataSources }) => dataSources.irriSatAPI.getMapsDates(),
  },
  Mutation: {
    mapDate: (_, { date }, { dataSources }) => dataSources.irriSatAPI.getMapsLayer(date)
  }
}

person Alex Mireles    schedule 23.04.2020    source источник
comment
вообще не стрелял? визуализировать ссылки/кнопки в цикле (чтобы узнать, как использовать переменные) - проверить инструменты/сеть разработчика (чтобы проверить, запущен ли запрос) ..... данные о результатах мутации не используются (вы можете использовать опцию обработчика мутации onCompleted - с другим setState - зачем перезаписывать данные из реквизита? использовать некоторый 'selectedDate'?) ... вы можете использовать useEffect для вызова обычного запроса (не мутации) при изменении option (зависимость эффекта, эффект срабатывает при запуске и принудительно setOption), потому что вы не меняете удаленные данные... переосмыслите состояние и поток данных   -  person xadm    schedule 23.04.2020


Ответы (1)


Есть несколько проблем с вашей функцией onChange.

Вы звоните getLayer дважды? Вам нужно вызвать его только один раз, в то же время, когда вы устанавливаете значение раскрывающегося списка. Кроме того, насколько я знаю, вам действительно не нужен onSelect.

import * as React from 'react';
import { useState } from 'react';
import { useMutation } from '@apollo/react-hooks';
import gql from 'graphql-tag';

const MAP_LAYER = gql`
    mutation MapLayer($date: String!) {
        mapDate(date: $date) {
            token
            mapid
            name
        }
    }
`;

const ContentWrapper = ({ children }) => <div>{...children}</div>;

const IrriSat: React.FC<any> = ({ data }) => {
    const [option, setOption] = useState((data?.mapDates as any)[0].date!);
    const [getLayer]: any = useMutation(MAP_LAYER);

    return (
        <ContentWrapper>
            <select
                value={option}
                onChange={(e: React.ChangeEvent<HTMLSelectElement>): void => {
                    setOption(e.target.value);
                    getLayer({ variables: { date: e.target.value } });
                }}
            >
                {data?.mapDates?.slice(0, 52).map(res => (
                    <option key={res?.date!} value={res?.date!}>
                        {res?.date}
                    </option>
                ))}
            </select>
        </ContentWrapper>
    );
};

export default IrriSat;

Очевидно, я изменил несколько вещей, чтобы избавиться от некоторых предупреждений редактора, но особое внимание уделите свойству onChange.

Совет: вы, вероятно, испытываете эти проблемы из-за экстремальной длины строки, в которую вы добавляете всю эту логику, сжатую. Установите расширение VS Code "Prettier - Code formatter". Включите формат VS Code при сохранении. Выгода.

person davidmwhynot    schedule 24.04.2020
comment
Да, я забыл удалить onSelect, когда задавал вопрос. Я не хотел вызывать getLayer дважды. Во всяком случае, до сих пор их ключевым моментом было установить дату для переменной getLayer. Теперь я получаю данные в GraphiQL в DevTools. Мне все еще нужно выяснить, как на самом деле получить доступ к данным. Очень ценю вашу помощь. - person Alex Mireles; 24.04.2020