#reactjs #graphql #apollo
Вопрос:
В моей базе данных хранится список элементов. Я написал запрос, чтобы случайным образом возвращать один элемент из списка при каждом нажатии кнопки. Я использую useLazyQuery и вызываю возвращаемую функцию для выполнения запроса, и она отлично работает. Я могу вызвать функцию повторной выборки при последующих нажатиях кнопок, и она правильно вернет другой случайный элемент.
Проблема возникает, когда я пытаюсь передать переменные в запрос. Я хочу предоставить различные критерии для запроса, чтобы адаптировать способ выполнения случайного выбора. Любые переменные, которые я передаю при первом вызове, повторяются при каждом повторном вызове, даже если они изменились. Я могу проследить, что они отличаются на клиенте, но распознаватель отслеживает предыдущие переменные.
// My query
const PICK = gql`
query Pick($options: PickOptionsInput) {
pick(options: $options) {
title
}
}
`;
// My lazy hook
const [pick, { data, refetch }] = useLazyQuery(PICK, {
fetchPolicy: "no-cache",
});
// My button
<MyButton
onPick={(options) =>
(refetch || pick)({ // Refetch unless this is the first click, then pick
variables: {
options // Options is a custom object of data used to control the pick
},
})
}
/>
Некоторые вещи, которые я пробовал:
- Различные политики кэширования
- Не использовать объект для параметров и определять каждый возможный параметр как отдельную переменную
Я действительно в тупике. Похоже, в документах говорится, что новые переменные должны использоваться, если они предоставлены при повторной выборке. Я не думаю, что политика кэширования имеет отношение к делу…Я получаю свежие результаты при каждом вызове, это просто устаревшие входные переменные.
Комментарии:
1. Вы пробовали с
fetch-policy
=network-only
также, пожалуйста, поделитесь своим кодом, как вы получаете варианты2. если «они разные на клиенте» (проверено в теле сетевого запроса?), то это просто не проблема клиента?
3. @MuhammadBilalBangash Параметры передаются обработчику «onPick», который я опубликовал. Я могу отследить его там прямо перед вызовом ленивого запроса и увидеть, что значения в объекте «параметры» изменяются правильно. Например, в зависимости от выбранной мной кнопки это может быть { минимум: 5000 } или { минимум: 4000, максимум: 8000 }. Я могу правильно видеть эти обновления, но независимо от того, каковы они, значение, которое я отслеживаю в своем распознавателе, всегда будет таким, какими были параметры при первом вызове ленивого запроса.
4. @xadm Переменные в полезной нагрузке запроса всегда являются теми, какими они были при первом вызове ленивого запроса. Я могу отследить их на клиенте прямо перед вызовом функции ленивого запроса, и они изменятся, но к моменту отправки запроса они будут такими же, как и при первом вызове. Таким образом, проблема, по-видимому, заключается в том, что передача новых значений в функцию ленивого запроса не имеет никакого эффекта.
5. @MuhammadBilalBangash Я перепробовал все политики кэширования. Они должны сделать правильные вещи в отношении-ответов — возврата (другими словами, отсутствие кэша вызывает новый запрос, кэш-сначала просто получает кэшированный ответ). Проблема в том, что переменные, отправленные на сервер, «застревают», несмотря на то, что они отличаются при передаче в ленивую функцию.
Ответ №1:
Наверное, только pick
так и называется …
… потому что для <MyBytton/>
этого нет изменения реквизита, нет onPick
переопределения — всегда используется первое определение обработчика (с первого рендеринга) и options
состояние с одного и того же времени …
Попробуйте передать все ( options
, pick
и refetch
) в качестве прямых реквизитов, чтобы принудительно выполнить повторную передачу и переопределить обработчик:
<MyButton
options={options}
pick={pick}
refetch={refetch}
onPick={(options) =>
(refetch || pick)({ // Refetch unless this is the first click, then pick
variables: {
options // Options is a custom object of data used to control the pick
},
})
}
/>
… или [лучше] определите обработчик, прежде чем передавать его в <MyButton/>
:
const pickHandler = useCallback(
(options) => {
if(refetch) {
console.log('refetch', options);
refetch( { variables: { options }});
} else {
console.log('pick', options);
pick( { variables: { options }});
}
},
[options, pick, refetch]
);
<MyButton onPick={pickHandler} />
Комментарии:
1. Я не могу этого сделать, потому что у меня нет вариантов, пока не нажата кнопка. Вот почему я использую ленивый обработчик. Приложение может много раз перерисовываться, прежде чем сработает «onPick».
2. … и это именно то, что вам нужно (и
useCallback
было разработано для этого) … обработчик обновляется только при изменении зависимости (не при каждом рендеринге) —options
находится в зависимости, будет актуален при необходимости … просто попробуйте, журнал скажет правду