#reactjs #react-query
#reactjs #реагирующий запрос
Вопрос:
Я использую useMutation()
перехват для задач crud для своего приложения, и я чувствую, что пишу много повторяющегося кода, изначально мой код был таким:
const [createList] = useCreateList(reset, err => setError(err.message));
const [updateList] = useCreateList(reset, err => setError(err.message));
const [deleteList] = useCreateList(reset, err => setError(err.message));
Где функция сброса такая:
const reset = () => {
setQsButtonStatus(null);
setSelectedList(null);
setTitleValue("");
}
Желаемый конечный код, который я бы хотел, это:
const {createList, updateList, deleteList} = useListMutation(reset, err => setError(err.message))
Я могу заставить это работать, но для меня код для этого выглядит очень грязным (опять много повторяющегося кода):
import * as List from "./list-api";
const useListMutation = (onSettled, onError) => {
const [createList] = useMutation(List.createList, {
onMutate: (listTitle) => {
queryCache.cancelQueries("lists");
const current = queryCache.getQueryData("lists");
queryCache.setQueryData("lists", prev => [...prev, {title: listTitle, id: uuidv4()}])
return () => queryCache.setQueryData("lists", current);
},
onError: (err, variables, rollback) => {rollback(); onError(err)},
onSettled: () => {
queryCache.invalidateQueries("lists");
onSettled();
}
})
const [updateList] = useMutation(List.updateList, {
onMutate: ({id, titleValue}) => {
queryCache.cancelQueries("lists");
const current = queryCache.getQueryData("lists");
queryCache.setQueryData("lists", prev => [
...prev.filter(list => list._id !== id),
{_id: id, title: titleValue}
])
return () => queryCache.setQueryData("lists", current);
},
onError: (err, variables, rollback) => {rollback(); onError(err)},
onSettled: () => {
queryCache.invalidateQueries("lists");
onSettled();
}
})
const [deleteList] = useMutation(List.deleteList, {
onMutate: (id) => {
queryCache.cancelQueries("lists");
const current = queryCache.getQueryData("lists");
queryCache.setQueryData("lists", prev => [
...prev.filter(list => list._id !== id),
])
return () => queryCache.setQueryData("lists", current);
},
onError: (err, variables, rollback) => {rollback(); onError(err)},
onSettled: () => {
queryCache.invalidateQueries("lists");
onSettled();
}
})
return {createList, updateList, deleteList};
}
export default useListMutation;
Есть ли лучший способ сделать это?
Ответ №1:
Одним из способов сокращения дублированного кода было бы создание getOptions
функции, которая возвращает функции onMutate
, onError
, и onSettled
. Это будет выглядеть примерно так:
const useListMutation = (onSettled, onError) => {
const getOptions = (onMutate) => ({
onMutate(data) {
queryCache.cancelQueries("lists")
const current = queryCache.getQueryData("lists")
onMutate(data)
return () => queryCache.setQueryData("lists", current)
},
onError(err, variables, rollback) {
rollback()
onError(err)
},
onSettled() {
queryCache.invalidateQueries("lists")
onSettled()
},
})
const [createList] = useMutation(
List.createList,
getOptions((listTitle) => {
queryCache.setQueryData("lists", (prev) => [
...prev,
{ title: listTitle, id: uuidv4() },
])
})
)
const [updateList] = useMutation(
List.updateList,
getOptions(({ id, titleValue }) => {
queryCache.setQueryData("lists", (prev) => [
...prev.filter((list) => list._id !== id),
{ _id: id, title: titleValue },
])
})
)
...
}