#reactjs #react-query
#reactjs #реагирующий запрос
Вопрос:
Я действительно не знаю, как четко задать вопрос, но сначала я вставлю свой код и спрошу ниже.
function useToDos() {
const queryCache = useQueryCache();
const fetchTodos = useQuery(
'fetchTodos',
() => client.get(paths.todos).then(({ data }: any) => data),
{ enabled: false }
);
const createTodo = async ({ name ) =>
await client.post(paths.todos, { name }).then(({ data }) => data);
return {
fetchTodos,
createTodo: useMutation(createTodo, {
onMutate: newItem => {
queryCache.cancelQueries('fetchTodos');
const previousTodos = queryCache.getQueryData('fetchTodos');
queryCache.setQueryData('fetchTodos', old => [
...old,
newItem,
]);
return () => queryCache.setQueryData('fetchTodos', previousTodos);
},
}),
};
}
Как вы можете видеть, я пытаюсь создать свои собственные пользовательские хуки, которые переносят функциональность react-query. Из-за этого мне нужно отключить мой fetchTodos
запрос, чтобы он не выполнялся сразу. Однако нарушает ли это всю выборку фоновых данных?
В частности, когда я запускаю createTodo
и onMutate
запускаю метод, я бы в идеале хотел, чтобы fetchTodos
обновление запроса выполнялось в фоновом режиме, чтобы мой список задач во внешнем интерфейсе обновлялся без повторной отправки запроса. Но, похоже, что при изначально отключенном запросе фоновое обновление не вступает в силу.
Поскольку я не думаю, что перенос перехватов react-query в библиотеку пользовательских перехватов — отличная идея, у меня, вероятно, будет больше вопросов об этой же настройке, но пока я начну здесь. Спасибо. 😊
Ответ №1:
Мутация автоматически не запускает повторную выборку. Способ добиться этого с помощью react-query — использовать QueryCache.invalidateQueries для аннулирования кэша после мутации. Из документов:
Метод invalidateQueries может использоваться для аннулирования и повторной выборки одного или нескольких запросов в кэше на основе их ключей запроса или любого другого функционально доступного свойства / состояния запроса. По умолчанию все совпадающие запросы немедленно помечаются как устаревшие, а активные запросы повторно извлекаются в фоновом режиме.
Таким образом, вы можете настроить useMutation
, чтобы аннулировать запрос, когда мутация установится. Пример:
function useToDos() {
const queryCache = useQueryCache();
const fetchTodos = useQuery(
'fetchTodos',
() => client.get(paths.todos).then(({ data }: any) => data),
{ enabled: false }
);
const createTodo = async ({ name ) =>
await client.post(paths.todos, { name }).then(({ data }) => data);
return {
fetchTodos,
createTodo: useMutation(createTodo, {
onMutate: newItem => {
queryCache.cancelQueries('fetchTodos');
const previousTodos = queryCache.getQueryData('fetchTodos');
queryCache.setQueryData('fetchTodos', old => [
...old,
newItem,
]);
return () => queryCache.setQueryData('fetchTodos', previousTodos);
},
onSettled: () => {
cache.invalidateQueries('fetchTodos');
}
}),
};
}
Комментарии:
1. В чем разница между
invalidateQueries
иrefetchQueries
?2. Look like
invalidateQueries
— это просто лучший вариантrefetchQueries
: github.com/tannerlinsley/react-query/issues /…3. Нет, на самом деле,
refetch
это заставит запросы извлекаться, несмотря ни на что, тогдаinvalidate
как только принудительная выборка, когда запросы не используются. Иногда мы хотим либо того, либо другого. У всех у них есть свое место.4. БОЛЬШОЕ вам СПАСИБО за ваш последний комментарий, который действительно не очень понятен в их документе!
5. Любопытно, почему недействительность
onSettled
вместоonSuccess
?
Ответ №2:
Как насчет разделения логики на два разных перехвата? Вместо монолита, подобного useToDos
?
Таким образом, у вас может быть перехват для выборки:
const fetchData = _ => client.get(paths.todos).then(({ data }: any) => data)
export default function useFetchTodo(
config = {
refetchOnWindowFocus: false,
enabled: false
}
) {
return useQuery('fetchData', fetchData, config)
}
И в вашем перехвате мутации вы можете выполнить повторную выборку вручную, прежде чем createTodo
import useFetchTodo from './useFetchTodo'
//
const { refetch } = useFetchTodo()
// before createTodo
refetch()
Комментарии:
1. Интересная настройка. Мне любопытно, хотя зачем вызывать повторную выборку перед созданием нового элемента? Насколько я понимаю, если запрос не отключен, всякий раз, когда я создаю новый элемент, этот кэш запросов будет обновляться вместе с ним, и мой список элементов в пользовательском интерфейсе будет обновлен. Я что-то упустил? Нужно ли мне вызывать повторную выборку независимо (если не делать оптимистичных ответов)?