Запрос React: чистый способ написания нескольких пользовательских перехватов useMutation?

#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 },
      ])
    })
  )

  ...
}