TanStack/query - 如何将我的文件从版本 v4 迁移到 v5

问题描述 投票:0回答:1

我正在尝试将我的库 tanstack/query v4 更新为 v5 (https://tanstack.com/query/v5/docs/react/guides/migration-to-v5),但我已阅读文档我在迁移版本时遇到问题,尤其是使用命令

命令:

$ npx jscodeshift@latest ./path/to/src/ \
  --extensions=ts,tsx \
  --parser=tsx \
  --transform=./node_modules/@tanstack/react-query/build/codemods/src/v5/remove-overloads/remove-overloads.js

我需要有人更新所有 4 个文件的语法,而不需要这个命令。

事件.组件.tsx

import React, { FC, useEffect, useState } from "react";
import { format, parseISO } from "date-fns";
import { twMerge } from "tailwind-merge";
import EventModal from "../event.modal";
import UpdateEvent from "./update.event";
import { toast } from "react-toastify";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import NProgress from "nprogress";
import { IEvent } from "../../api/types";
import { deleteEventFn } from "../../api/eventApi";

type EventItemProps = {
  event: IEvent;
};

const EventItem: FC<EventItemProps> = ({ event }) => {
  const [openSettings, setOpenSettings] = useState(false);
  const [openEventModal, setOpenEventModal] = useState(false);

  // My addition
  useEffect(() => {
    const handleOutsideClick = (event: MouseEvent) => {
      const target = event.target as HTMLElement;
      const dropdown = document.getElementById(`settings-dropdown-${event.id}`);

      if (dropdown && !dropdown.contains(target)) {
        setOpenSettings(false);
      }
    };
    document.addEventListener("mousedown", handleOutsideClick);

    return () => {
      document.removeEventListener("mousedown", handleOutsideClick);
    };
  }, [event.id]);

  const queryClient = useQueryClient();
  const { mutate: deleteEvent } = useMutation({
    mutationFn: (eventId: string) => deleteEventFn(eventId),
    onMutate() {
      NProgress.start();
    },
    onSuccess(data) {
      queryClient.invalidateQueries({
        queryKey: ["getEvents"]
      });
      toast("Event deleted successfully", {
        type: "warning",
        position: "top-right",
      });
      NProgress.done();
    },
    onError(error: any) {
      const resMessage =
        error.response.data.message ||
        error.response.data.detail ||
        error.message ||
        error.toString();
      toast(resMessage, {
        type: "error",
        position: "top-right",
      });
      NProgress.done();
    },
  });

  const onDeleteHandler = (eventId: string) => {
    if (window.confirm("Are you sure")) {
      deleteEvent(eventId);
    }
  };
  return (
    <>
     ...
    </>
  );
};

export default EventItem;

更新.event.tsx

import { FC, useEffect } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { twMerge } from "tailwind-merge";
import { object, string, TypeOf } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { LoadingButton } from "../LoadingButton";
import { toast } from "react-toastify";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { IEvent } from "../../api/types";
import { updateEventFn } from "../../api/eventApi";

type IUpdateEventProps = {
  event: IEvent;
  setOpenEventModal: (open: boolean) => void;
};

const updateEventSchema = object({
  title: string().min(1, "Title is required"),
  content: string().min(1, "Content is required"),
});

export type UpdateEventInput = TypeOf<typeof updateEventSchema>;

const UpdateEvent: FC<IUpdateEventProps> = ({ event, setOpenEventModal }) => {
  const methods = useForm<UpdateEventInput>({
    resolver: zodResolver(updateEventSchema),
  });

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = methods;

  useEffect(() => {
    if (event) {
      methods.reset(event);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const queryClient = useQueryClient();
  const { mutate: updateEvent } = useMutation({
    mutationFn: ({ eventId, event }: { eventId: string; event: UpdateEventInput }) =>
      updateEventFn(eventId, event),
    onSuccess(data) {
      queryClient.invalidateQueries({
        queryKey: ["getEvents"]
      });
      setOpenEventModal(false);
      toast("Event updated successfully", {
        type: "success",
        position: "top-right",
      });
    },
    onError(error: any) {
      setOpenEventModal(false);
      const resMessage =
        error.response.data.message ||
        error.response.data.detail ||
        error.message ||
        error.toString();
      toast(resMessage, {
        type: "error",
        position: "top-right",
      });
    },
  });

  const onSubmitHandler: SubmitHandler<UpdateEventInput> = async (data) => {
    updateEvent({ eventId: event.id, event: data });
  };
  return (
    <section>
     ...
    </section>
  );
};

export default UpdateEvent;

创建.event.tsx

import { FC } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { twMerge } from "tailwind-merge";
import { object, string, TypeOf } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { LoadingButton } from "../LoadingButton";
import { toast } from "react-toastify";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { createEventFn } from "../../api/eventApi";
import NProgress from "nprogress";

type ICreateEventProps = {
  setOpenEventModal: (open: boolean) => void;
};

const createEventSchema = object({
  title: string().min(1, "Title is required"),
  content: string().min(1, "Content is required"),
});

export type CreateEventInput = TypeOf<typeof createEventSchema>;

const CreateEvent: FC<ICreateEventProps> = ({ setOpenEventModal }) => {
  const methods = useForm<CreateEventInput>({
    resolver: zodResolver(createEventSchema),
  });

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = methods;

  const queryClient = useQueryClient();

  const { mutate: createEvent } = useMutation({
    mutationFn: (event: CreateEventInput) => createEventFn(event),
    onMutate() {
      NProgress.start();
    },
    onSuccess(data) {
      queryClient.invalidateQueries({
        queryKey: ["getEvents"]
      });
      setOpenEventModal(false);
      NProgress.done();
      toast("Event created successfully", {
        type: "success",
        position: "top-right",
      });
    },
    onError(error: any) {
      setOpenEventModal(false);
      NProgress.done();
      const resMessage =
        error.response.data.message ||
        error.response.data.detail ||
        error.message ||
        error.toString();
      toast(resMessage, {
        type: "error",
        position: "top-right",
      });
    },
  });

  const onSubmitHandler: SubmitHandler<CreateEventInput> = async (data) => {
    createEvent(data);
  };
  return (
    <section>
      ...
    </section>
  );
};

export default CreateEvent;

应用程序.tsx

import "react-toastify/dist/ReactToastify.css";
import {
  QueryClient,
  QueryClientProvider,
  useQuery,
} from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { toast, ToastContainer } from "react-toastify";
import { getEventsFn } from "./api/eventApi";
import EventModal from "./components/event.modal";
import CreateEvent from "./components/events/create.event";
import EventItem from "./components/events/event.component";
import NProgress from "nprogress";

function AppContent() {
  const [openEventModal, setOpenEventModal] = useState(false);

  const {
    data: events,
    isLoading,
    isFetching,
  } = useQuery({
    queryKey: ["getEvents"],
    queryFn: () => getEventsFn(),
    staleTime: 5 * 1000,
    select: (data) => data.events,
    onSuccess() {
      NProgress.done();
    },
    onError(error: any) {
      const resMessage =
        error.response.data.message ||
        error.response.data.detail ||
        error.message ||
        error.toString();
      toast(resMessage, {
        type: "error",
        position: "top-right",
      });
      NProgress.done();
    },
  });

  useEffect(() => {
    if (isLoading || isFetching) {
      NProgress.start();
    }
  }, [isLoading, isFetching]);

  return (
    <div className="2xl:max-w-[90rem] max-w-[68rem] mx-auto">
      <div className="m-8 grid grid-cols-[repeat(auto-fill,_320px)] gap-7 grid-rows-[1fr]">
        <div className="p-4 min-h-[18rem] bg-white rounded-lg border border-gray-200 shadow-md flex flex-col items-center justify-center">
          <div
            onClick={() => setOpenEventModal(true)}
            className="flex items-center justify-center h-20 w-20 border-2 border-dashed border-ct-blue-600 rounded-full text-ct-blue-600 text-5xl cursor-pointer"
          >
            <i className="bx bx-plus"></i>
          </div>
          <h4
            onClick={() => setOpenEventModal(true)}
            className="text-lg font-medium text-ct-blue-600 mt-5 cursor-pointer"
          >
            Add new event
          </h4>
        </div>
        {/* Event Items */}

        {events?.map((event) => (
          <EventItem key={event.id} event={event} />
        ))}

        {/* Create Event Modal */}
        <EventModal
          openEventModal={openEventModal}
          setOpenEventModal={setOpenEventModal}
        >
          <CreateEvent setOpenEventModal={setOpenEventModal} />
        </EventModal>
      </div>
    </div>
  );
}

function App() {
  const [queryClient] = useState(() => new QueryClient());
  return (
    <>
      <QueryClientProvider client={queryClient}>

      </QueryClientProvider>
    </>
  );
}

export default App;
javascript reactjs migration react-query tanstackreact-query
1个回答
-1
投票

您在使用此命令时遇到了什么问题?

© www.soinside.com 2019 - 2024. All rights reserved.