skelaw
skelaw

Reputation: 282

Why does react-query query not work when parameter from router.query returns undefined on refresh?

When page is refreshed query is lost, disappears from react-query-devtools.

Before Next.js, I was using a react and react-router where I would pull a parameter from the router like this:

const { id } = useParams();

It worked then. With the help of the, Next.js Routing documentation I have replaced useParams with:

import { usePZDetailData } from "../../hooks/usePZData";
import { useRouter } from "next/router";
const PZDetail = () => {
  const router = useRouter();
  const { id } = router.query;
  const { } = usePZDetailData(id);

  return <></>;
};

export default PZDetail;

Does not work on refresh. I found a similar topic, but manually using 'refetch' from react-query in useEffects doesn't seem like a good solution. How to do it then?

Edit

Referring to the comment, I am enclosing the rest of the code, the react-query hook. Together with the one already placed above, it forms a whole.

const fetchPZDetailData = (id) => {
  return axiosInstance.get(`documents/pzs/${id}`);
};

export const usePZDetailData = (id) => {
  return useQuery(["pzs", id], () => fetchPZDetailData(id), {});
};

Edit 2

I attach PZList page code with <Link> implementation

import Link from "next/link";
import React from "react";
import TableModel from "../../components/TableModel";
import { usePZSData } from "../../hooks/usePZData";
import { createColumnHelper } from "@tanstack/react-table";

type PZProps = {
  id: number;
  title: string;
  entry_into_storage_date: string;
};

const index = () => {
  const { data: PZS, isLoading } = usePZSData();
  const columnHelper = createColumnHelper<PZProps>();
  const columns = [
    columnHelper.accessor("title", {
      cell: (info) => (
        <span>
          <Link
            href={`/pzs/${info.row.original.id}`}
          >{`Dokument ${info.row.original.id}`}</Link>
        </span>
      ),
      header: "Tytuł",
    }),
    columnHelper.accessor("entry_into_storage_date", {
      header: "Data wprowadzenia na stan ",
    }),
  ];
  return (
    <div>
      {isLoading ? (
        "loading "
      ) : (
        <TableModel data={PZS?.data} columns={columns} />
      )}
    </div>
  );
};

export default index;

Upvotes: 1

Views: 2968

Answers (1)

juliomalves
juliomalves

Reputation: 50408

What you're experiencing is due to the Next.js' Automatic Static Optimization.

If getServerSideProps or getInitialProps is present in a page, Next.js will switch to render the page on-demand, per-request (meaning Server-Side Rendering).

If the above is not the case, Next.js will statically optimize your page automatically by prerendering the page to static HTML.

During prerendering, the router's query object will be empty since we do not have query information to provide during this phase. After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.

Since your page doesn't have getServerSideProps or getInitialProps, Next.js statically optimizes it automatically by prerendering it to static HTML. During this process the query string is an empty object, meaning in the first render router.query.id will be undefined. The query string value is only updated after hydration, triggering another render.


In your case, you can work around this by disabling the query if id is undefined. You can do so by passing the enabled option to the useQuery call.

export const usePZDetailData = (id) => {
    return useQuery(["pzs", id], () => fetchPZDetailData(id), {
        enabled: id
    });
};

This will prevent making the request to the API if id is not defined during first render, and will make the request once its value is known after hydration.

Upvotes: 4

Related Questions