diff --git a/templates/next/components/common/Layout.tsx b/templates/next/components/common/Layout.tsx index a2d41bb9..0c2798fb 100644 --- a/templates/next/components/common/Layout.tsx +++ b/templates/next/components/common/Layout.tsx @@ -1,14 +1,14 @@ import { ReactNode, useState } from "react"; -import { DehydratedState, Hydrate, QueryClient, QueryClientProvider } from "react-query"; +import { DehydratedState, HydrationBoundary, QueryClient, QueryClientProvider } from "@tanstack/react-query"; const Layout = ({ children, dehydratedState }: { children: ReactNode, dehydratedState: DehydratedState }) => { const [queryClient] = useState(() => new QueryClient()); return ( <QueryClientProvider client={queryClient}> - <Hydrate state={dehydratedState}> + <HydrationBoundary state={dehydratedState}> {children} - </Hydrate> + </HydrationBoundary> </QueryClientProvider> ); } diff --git a/templates/next/components/foo/Form.tsx b/templates/next/components/foo/Form.tsx index 3612d618..59fa58c2 100644 --- a/templates/next/components/foo/Form.tsx +++ b/templates/next/components/foo/Form.tsx @@ -2,9 +2,9 @@ import { FunctionComponent, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/router"; import { ErrorMessage{{#if hasManyRelations}}, Field, FieldArray{{/if}}, Formik } from "formik"; -import { useMutation } from "react-query"; +import { useMutation } from "@tanstack/react-query"; -import { fetch, FetchError, FetchResponse } from "../../utils/dataAccess"; +import { fetchApi, FetchError, FetchResponse } from "../../utils/dataAccess"; import { {{{ucf}}} } from '../../types/{{{ucf}}}'; interface Props { @@ -20,28 +20,30 @@ interface DeleteParams { } const save{{{ucf}}} = async ({ values }: SaveParams) => - await fetch<{{ucf}}>(!values["@id"] ? "/{{{name}}}" : values["@id"], { + await fetchApi<{{ucf}}>(!values["@id"] ? "/{{{name}}}" : values["@id"], { method: !values["@id"] ? "POST" : "PUT", body: JSON.stringify(values), }); -const delete{{{ucf}}} = async (id: string) => await fetch<{{ucf}}>(id, { method: "DELETE" }); +const delete{{{ucf}}} = async (id: string) => await fetchApi<{{ucf}}>(id, { method: "DELETE" }); export const Form: FunctionComponent<Props> = ({ {{{lc}}} }) => { const [, setError] = useState<string | null>(null); const router = useRouter(); - const saveMutation = useMutation<FetchResponse<{{ucf}}> | undefined, Error|FetchError, SaveParams>((saveParams) => save{{{ucf}}}(saveParams)); + const saveMutation = useMutation<FetchResponse<{{ucf}}> | undefined, Error|FetchError, SaveParams>({mutationFn: (saveParams) => save{{{ucf}}}(saveParams)}); - const deleteMutation = useMutation<FetchResponse<{{ucf}}> | undefined, Error|FetchError, DeleteParams>(({ id }) => delete{{{ucf}}}(id), { - onSuccess: () => { - router.push("/{{{lc}}}s"); - }, - onError: (error)=> { - setError(`Error when deleting the resource: ${error}`); - console.error(error); - } - }); + const deleteMutation = useMutation<FetchResponse<{{ucf}}> | undefined, Error|FetchError, DeleteParams>( + { + mutationFn: ({ id }) => delete{{{ucf}}}(id), + onSuccess: () => { + router.push("/{{{lc}}}s"); + }, + onError: (error)=> { + setError(`Error when deleting the resource: ${error}`); + console.error(error); + }, + }); const handleDelete = () => { if (!{{lc}} || !{{lc}}["@id"]) return; @@ -90,7 +92,7 @@ export const Form: FunctionComponent<Props> = ({ {{{lc}}} }) => { isValid: true, msg: `Element ${isCreation ? "created" : "updated"}.`, }); - router.push("/{{{name}}}"); + router.push("/{{{lc}}}s"); }, onError: (error) => { setStatus({ diff --git a/templates/next/components/foo/PageList.tsx b/templates/next/components/foo/PageList.tsx index 6c89b089..8add3d25 100644 --- a/templates/next/components/foo/PageList.tsx +++ b/templates/next/components/foo/PageList.tsx @@ -1,23 +1,23 @@ import { NextComponentType, NextPageContext } from "next"; import { useRouter } from "next/router"; import Head from "next/head"; -import { useQuery } from "react-query"; +import { useQuery } from "@tanstack/react-query"; import Pagination from "../common/Pagination"; import { List } from "./List"; import { PagedCollection } from "../../types/collection"; import { {{{ucf}}} } from "../../types/{{{ucf}}}"; -import { fetch, FetchResponse, parsePage } from "../../utils/dataAccess"; +import { fetchApi, FetchResponse, parsePage } from "../../utils/dataAccess"; import { useMercure } from "../../utils/mercure"; export const get{{{ucf}}}sPath = (page?: string | string[] | undefined) => `/{{{name}}}${typeof page === 'string' ? `?page=${page}` : ''}`; -export const get{{{ucf}}}s = (page?: string | string[] | undefined) => async () => await fetch<PagedCollection<{{{ucf}}}>>(get{{{ucf}}}sPath(page)); +export const get{{{ucf}}}s = (page?: string | string[] | undefined) => async () => await fetchApi<PagedCollection<{{{ucf}}}>>(get{{{ucf}}}sPath(page)); const getPagePath = (path: string) => `/{{{lc}}}s/page/${parsePage("{{{name}}}", path)}`; export const PageList: NextComponentType<NextPageContext> = () => { const { query: { page } } = useRouter(); const { data: { data: {{lc}}s, hubURL } = { hubURL: null } } = - useQuery<FetchResponse<PagedCollection<{{{ucf}}}>> | undefined>(get{{{ucf}}}sPath(page), get{{{ucf}}}s(page)); + useQuery<FetchResponse<PagedCollection<{{{ucf}}}>> | undefined, Error, FetchResponse<PagedCollection<{{{ucf}}}>> | undefined>({queryKey: [get{{{ucf}}}sPath(page)], queryFn: get{{{ucf}}}s(page)}); const collection = useMercure({{lc}}s, hubURL); if (!collection || !collection["{{{hydraPrefix}}}member"]) return null; diff --git a/templates/next/components/foo/Show.tsx b/templates/next/components/foo/Show.tsx index ea06a6e6..1e98774f 100644 --- a/templates/next/components/foo/Show.tsx +++ b/templates/next/components/foo/Show.tsx @@ -4,7 +4,7 @@ import { useRouter } from "next/router"; import Head from "next/head"; {{#if hasRelations}}import ReferenceLinks from "../common/ReferenceLinks";{{/if}} -import { fetch, getItemPath } from "../../utils/dataAccess"; +import { fetchApi, getItemPath } from "../../utils/dataAccess"; import { {{{ucf}}} } from "../../types/{{{ucf}}}"; interface Props { @@ -21,7 +21,7 @@ export const Show: FunctionComponent<Props> = ({ {{{lc}}}, text }) => { if (!window.confirm("Are you sure you want to delete this item?")) return; try { - await fetch({{{lc}}}["@id"], { method: "DELETE" }); + await fetchApi({{{lc}}}["@id"], { method: "DELETE" }); router.push("/{{{lc}}}s"); } catch (error) { setError("Error when deleting the resource."); diff --git a/templates/next/pages/_app.tsx b/templates/next/pages/_app.tsx index dda01d4b..41097bdf 100644 --- a/templates/next/pages/_app.tsx +++ b/templates/next/pages/_app.tsx @@ -1,6 +1,6 @@ import "../styles/style.css"; import type { AppProps } from "next/app"; -import type { DehydratedState } from "react-query"; +import type { DehydratedState } from "@tanstack/react-query"; import Layout from "../components/common/Layout"; diff --git a/templates/next/pages/foos/[id]/edit.tsx b/templates/next/pages/foos/[id]/edit.tsx index 59b650ac..d034ac75 100644 --- a/templates/next/pages/foos/[id]/edit.tsx +++ b/templates/next/pages/foos/[id]/edit.tsx @@ -2,20 +2,20 @@ import { GetStaticPaths, GetStaticProps, NextComponentType, NextPageContext } fr import DefaultErrorPage from "next/error"; import Head from "next/head"; import { useRouter } from "next/router"; -import { dehydrate, QueryClient, useQuery } from "react-query"; +import { dehydrate, QueryClient, useQuery } from "@tanstack/react-query"; import { Form } from "../../../components/{{{lc}}}/Form"; import { PagedCollection } from "../../../types/collection"; import { {{{ucf}}} } from "../../../types/{{{ucf}}}"; -import { fetch, FetchResponse, getItemPaths } from "../../../utils/dataAccess"; +import { fetchApi, FetchResponse, getItemPaths } from "../../../utils/dataAccess"; -const get{{{ucf}}} = async (id: string|string[]|undefined) => id ? await fetch<{{{ucf}}}>(`/{{{name}}}/${id}`) : Promise.resolve(undefined); +const get{{{ucf}}} = async (id: string|string[]|undefined) => id ? await fetchApi<{{{ucf}}}>(`/{{{name}}}/${id}`) : Promise.resolve(undefined); const Page: NextComponentType<NextPageContext> = () => { const router = useRouter(); const { id } = router.query; - const { data: { data: {{lc}} } = {} } = useQuery<FetchResponse<{{{ucf}}}> | undefined>(['{{{lc}}}', id], () => get{{{ucf}}}(id)); + const { data: { data: {{lc}} } = {} } = useQuery<FetchResponse<{{{ucf}}}> | undefined, Error, FetchResponse<{{{ucf}}}> | undefined>({queryKey: ['{{{lc}}}', id], queryFn: () => get{{{ucf}}}(id)}); if (!{{{lc}}}) { return <DefaultErrorPage statusCode={404} />; @@ -36,7 +36,7 @@ const Page: NextComponentType<NextPageContext> = () => { export const getStaticProps: GetStaticProps = async ({ params: { id } = {} }) => { if (!id) throw new Error('id not in query param'); const queryClient = new QueryClient(); - await queryClient.prefetchQuery(["{{{lc}}}", id], () => get{{{ucf}}}(id)); + await queryClient.prefetchQuery({queryKey: ["{{{lc}}}", id], queryFn: () => get{{{ucf}}}(id)}); return { props: { @@ -47,7 +47,7 @@ export const getStaticProps: GetStaticProps = async ({ params: { id } = {} }) => }; export const getStaticPaths: GetStaticPaths = async () => { - const response = await fetch<PagedCollection<{{{ucf}}}>>("/{{{name}}}"); + const response = await fetchApi<PagedCollection<{{{ucf}}}>>("/{{{name}}}"); const paths = await getItemPaths(response, "{{{name}}}", '/{{{lc}}}s/[id]/edit'); return { diff --git a/templates/next/pages/foos/[id]/index.tsx b/templates/next/pages/foos/[id]/index.tsx index 2d837925..f2319e45 100644 --- a/templates/next/pages/foos/[id]/index.tsx +++ b/templates/next/pages/foos/[id]/index.tsx @@ -2,22 +2,22 @@ import { GetStaticPaths, GetStaticProps, NextComponentType, NextPageContext } fr import DefaultErrorPage from "next/error"; import Head from "next/head"; import { useRouter } from "next/router"; -import { dehydrate, QueryClient, useQuery } from "react-query"; +import { dehydrate, QueryClient, useQuery } from "@tanstack/react-query"; import { Show } from "../../../components/{{{lc}}}/Show"; import { PagedCollection } from "../../../types/collection"; import { {{{ucf}}} } from "../../../types/{{{ucf}}}"; -import { fetch, FetchResponse, getItemPaths } from "../../../utils/dataAccess"; +import { fetchApi, FetchResponse, getItemPaths } from "../../../utils/dataAccess"; import { useMercure } from "../../../utils/mercure"; -const get{{{ucf}}} = async (id: string|string[]|undefined) => id ? await fetch<{{{ucf}}}>(`/{{{name}}}/${id}`) : Promise.resolve(undefined); +const get{{{ucf}}} = async (id: string|string[]|undefined) => id ? await fetchApi<{{{ucf}}}>(`/{{{name}}}/${id}`) : Promise.resolve(undefined); const Page: NextComponentType<NextPageContext> = () => { const router = useRouter(); const { id } = router.query; const { data: { data: {{lc}}, hubURL, text } = { hubURL: null, text: '' } } = - useQuery<FetchResponse<{{{ucf}}}> | undefined>(['{{{lc}}}', id], () => get{{{ucf}}}(id)); + useQuery<FetchResponse<{{{ucf}}}> | undefined, Error, FetchResponse<{{{ucf}}}> | undefined>({queryKey: ['{{{lc}}}', id], queryFn: () => get{{{ucf}}}(id)}); const {{{lc}}}Data = useMercure({{lc}}, hubURL); if (!{{{lc}}}Data) { @@ -39,7 +39,7 @@ const Page: NextComponentType<NextPageContext> = () => { export const getStaticProps: GetStaticProps = async ({ params: { id } = {} }) => { if (!id) throw new Error('id not in query param'); const queryClient = new QueryClient(); - await queryClient.prefetchQuery(["{{{lc}}}", id], () => get{{{ucf}}}(id)); + await queryClient.prefetchQuery({queryKey: ["{{{lc}}}", id], queryFn: () => get{{{ucf}}}(id)}); return { props: { @@ -50,7 +50,7 @@ export const getStaticProps: GetStaticProps = async ({ params: { id } = {} }) => }; export const getStaticPaths: GetStaticPaths = async () => { - const response = await fetch<PagedCollection<{{{ucf}}}>>("/{{{name}}}"); + const response = await fetchApi<PagedCollection<{{{ucf}}}>>("/{{{name}}}"); const paths = await getItemPaths(response, "{{{name}}}", '/{{{lc}}}s/[id]'); return { diff --git a/templates/next/pages/foos/index.tsx b/templates/next/pages/foos/index.tsx index 6a48ec8e..4b211e43 100644 --- a/templates/next/pages/foos/index.tsx +++ b/templates/next/pages/foos/index.tsx @@ -1,11 +1,11 @@ import { GetStaticProps } from "next"; -import { dehydrate, QueryClient } from "react-query"; +import { dehydrate, QueryClient } from "@tanstack/react-query"; import { PageList, get{{{ucf}}}s, get{{{ucf}}}sPath } from "../../components/{{{lc}}}/PageList"; export const getStaticProps: GetStaticProps = async () => { const queryClient = new QueryClient(); - await queryClient.prefetchQuery(get{{{ucf}}}sPath(), get{{{ucf}}}s()); + await queryClient.prefetchQuery({queryKey: [get{{{ucf}}}sPath()], queryFn: get{{{ucf}}}s()}); return { props: { diff --git a/templates/next/pages/foos/page/[page].tsx b/templates/next/pages/foos/page/[page].tsx index bc3f0251..17642875 100644 --- a/templates/next/pages/foos/page/[page].tsx +++ b/templates/next/pages/foos/page/[page].tsx @@ -1,14 +1,14 @@ import { GetStaticPaths, GetStaticProps } from "next"; -import { dehydrate, QueryClient } from "react-query"; +import { dehydrate, QueryClient } from "@tanstack/react-query"; import { PageList, get{{{ucf}}}s, get{{{ucf}}}sPath } from "../../../components/{{{lc}}}/PageList"; import { PagedCollection } from "../../../types/collection"; import { {{{ucf}}} } from "../../../types/{{{ucf}}}"; -import { fetch, getCollectionPaths } from "../../../utils/dataAccess"; +import { fetchApi, getCollectionPaths } from "../../../utils/dataAccess"; export const getStaticProps: GetStaticProps = async ({ params: { page } = {} }) => { const queryClient = new QueryClient(); - await queryClient.prefetchQuery(get{{{ucf}}}sPath(page), get{{{ucf}}}s(page)); + await queryClient.prefetchQuery({queryKey: [get{{{ucf}}}sPath(page)], queryFn: get{{{ucf}}}s(page)}); return { props: { @@ -19,7 +19,7 @@ export const getStaticProps: GetStaticProps = async ({ params: { page } = {} }) }; export const getStaticPaths: GetStaticPaths = async () => { - const response = await fetch<PagedCollection<{{{ucf}}}>>("/{{{name}}}"); + const response = await fetchApi<PagedCollection<{{{ucf}}}>>("/{{{name}}}"); const paths = await getCollectionPaths(response, "{{{name}}}", "/{{{lc}}}s/page/[page]"); return { diff --git a/templates/next/utils/dataAccess.ts b/templates/next/utils/dataAccess.ts index 6e9b7f32..5643acd1 100644 --- a/templates/next/utils/dataAccess.ts +++ b/templates/next/utils/dataAccess.ts @@ -1,5 +1,3 @@ -import isomorphicFetch from "isomorphic-unfetch"; - import { PagedCollection } from "../types/collection"; import { Item } from "../types/item"; import { ENTRYPOINT } from "../config/entrypoint"; @@ -34,7 +32,7 @@ const extractHubURL = (response: Response): null | URL => { return matches && matches[1] ? new URL(matches[1], ENTRYPOINT) : null; }; -export const fetch = async <TData>(id: string, init: RequestInit = {}): Promise<FetchResponse<TData>|undefined> => { +export const fetchApi = async <TData>(id: string, init: RequestInit = {}): Promise<FetchResponse<TData>|undefined> => { if (typeof init.headers === "undefined") init.headers = {}; if (!init.headers.hasOwnProperty("Accept")) init.headers = { ...init.headers, Accept: MIME_TYPE }; @@ -45,7 +43,7 @@ export const fetch = async <TData>(id: string, init: RequestInit = {}): Promise< ) init.headers = { ...init.headers, "Content-Type": MIME_TYPE }; - const resp = await isomorphicFetch(ENTRYPOINT + id, init); + const resp = await fetch(ENTRYPOINT + id, init); if (resp.status === 204) return; const text = await resp.text(); @@ -93,7 +91,7 @@ export const getItemPaths = async <TData extends Item>(response: FetchResponse<P for (let page = 2; page <= lastPage; page++) { paths.push( - ...(await fetch<PagedCollection<TData>>(`/${resourceName}?page=${page}`)) + ...(await fetchApi<PagedCollection<TData>>(`/${resourceName}?page=${page}`)) ?.data["{{{hydraPrefix}}}member"]?.map((resourceData) => getItemPath(resourceData['@id'] ?? '', pathTemplate)) ?? [] ); }