Как предотвратить использование useQuery при изменении состояния - React, Apollo, GraphQL - PullRequest
0 голосов
/ 22 марта 2020

Я использую React Apollo для получения данных с моего сервера. Когда моя страница загружается, я использую useQuery для извлечения данных. Это отлично работает. Проблема заключается в том, что когда я изменяю форму поиска, это обновляет состояние, которое вызывает нежелательный повторный рендеринг, который снова вызывает сервер.

Я хочу вызывать сервер только тогда, когда страница загружается и когда я нажмите кнопку поиска.

useQuery:

const { loading: loadingLessons, error: lessonsError, data: lessons } = useQuery(
 LESSON_BY_PARAMS,
    {
      variables: { findLessonsInput: searchParams },
    },
);

Когда я изменяю поле формы, он вызывает updateFormField, который обновляет состояние избыточности, вызывая повторную визуализацию

<Autocomplete
  options={categories}
  getOptionLabel={(option: any) => option.label}
  inputValue={form.category}
  defaultValue={() => {
    const value = categories.find(option => option.label === form.category);
    return value;
  }}
  onChange={(event, value) => updateFormField('category', value?.label)}
  renderInput={params => (
    <TextField {...params} label="Category" variant="outlined" fullWidth />
  )}
/>

Я использую реагирующие крючки.

Ответы [ 2 ]

1 голос
/ 22 марта 2020

Обратите внимание на параметр skip , который можно использовать для полного пропуска запроса. Вы можете сделать что-то вроде этого:

const [skip, setSkip] = React.useState(false)
const { loading, data } = useQuery(QUERY, { skip })

React.useEffect(() => {
  // check whether data exists
  if (!loading && !!data) {
    setSkip(true)
  }
}, [data, loading])

Итак, как только данные вернутся, вы просто установите для параметра skip значение true. Если вы хотите сделать запрос, вы должны обработать onClick на кнопке поиска (просто setSkip (false)).

0 голосов
/ 23 марта 2020

Спасибо за предложение @Vadim Sheremetov, однако я решил переместить вызов API в функцию redux-thunk:

Когда страница загружается, я отправляю действие, передавая ей параметры поиска и клиент apollo:

const client = useApolloClient();

useEffect(() => {
    loadLessons(searchParams, client);
}, [location.search]);

const mapDispatchToProps = dispatch => {
  return {
    loadLessons: (searchParams, client) =>
      dispatch(loadLessonsAction(searchParams, client)),
  };
};

Действие вызывает избыточную функцию thunk, которая затем отправляет другое действие, обновляющее состояние:

actions.ts:

export function loadLessonsAction(searchParams: any, client: ApolloClient<object>): 
any {
  return async function(dispatch) {
    try {
      const { data } = await client.query({
        query: LESSON_BY_PARAMS,
        variables: { findLessonsInput: searchParams },
      });
      dispatch(loadLessonsSuccessAction(data.lessonsByParams));
    } catch (error) {}
  };
}

export function loadLessonsSuccessAction(lessons: any[]): FilterPanelActionTypes {
  return {
    type: LOAD_LESSONS_SUCCESS,
    payload: lessons,
  };
}

reducer.ts:

case LOAD_LESSONS_SUCCESS: {
  return {
    ...state,
    lessons: action.payload.lessons,
    lessonCount: action.payload.count,
  };
}
...