0

I'm working on a college project which is a small restaurant page with an admin to add food and have it reflected in the frontend. The page is made using Next.js, Prisma.io and Postgres. The API is made using the same API of Next.js.

The logic of the page, summarized, is this: Each food is placed in a category, so I have the category "Tacos" and inside it I can put "Chicken Tacos", "Beef Tacos", etc.

In development mode everything works as it should, connections, queries, admin, etc. But when I send my page to production, the select queries remain cached. That is, if from the administrator I add a new meal, this is reflected in the administrator table but not in the frontend of the clients. Even if I visit the API from Postman or Thunderclient, it returns data without the new meal I added.

I did several tests and even did fetch with other packages (like node-postgres) and still, the data is not refreshed, it's as if Next.js made a cached copy of those results.

Here are some important code sections:

/api/comidas to create a new meal

import { prismaExclude } from "@/utils";
import { NextResponse } from "next/server";
import prisma from "../db-connection";

export const POST = async (req: Request) => {
  try {
    const { nombreProducto, descripcion, precio, categoriaId, imageSrc } =
      (await req.json()) as ReqInputs;

    await prisma.producto.create({
      data: {
        nombreProducto,
        descripcion,
        precio,
        categoria: {
          connect: {
            id: categoriaId,
          },
        },
        imageSrc,
      },
    });

    return NextResponse.json(
      {
        message: "Comida created successfully",
      },
      { status: 201 }
    );
  } catch (error) {
    return NextResponse.json(
      {
        message: `Error trying to create a food: ${error}`,
      },
      { status: 500 }
    );
  }
};

/api/categorias/comidas To get categories and meals that belong to each category:

import { NextResponse } from "next/server";
import prisma from "../../db-connection";

export const GET = async () => {
  const categorias = await prisma.categoria.findMany({
    include: {
      Producto: true,
    },
  });

  return NextResponse.json({
    message: "Categorias retreived successfully",
    categorias,
  });
};

Fetch of meals (they do refresh when a new meal is added):

import { ComidaFull } from "@/types";
import { useQuery } from "react-query";

export default function useComidas() {
  const { data, refetch } = useQuery<{
    message: string;
    comidas: ComidaFull[];
  }>(["comidas"], getComidas);

  return {
    comidas: data?.comidas,
    reloadComidas: refetch,
  };
}

export const getComidas = () => fetch("/api/comidas").then((res) => res.json());

Fetch of the categories that include meals (these NOT reflect the changes made from the administrator)

import { CategoriaWithComida } from "@/types";
import { useQuery } from "react-query";

export default function useGetWithFoods() {
  const { data, refetch } = useQuery<{
    message: string;
    categorias: CategoriaWithComida[];
  }>(["categoria", "comida"], getCategoriaWithFood);

  return {
    categorias: data?.categorias,
    reloadCategoriasComidas: refetch,
  };
}

export const getCategoriaWithFood = () =>
  fetch("/api/categorias/comidas").then((res) => res.json());

NOTE: The postgres db I use is running in a Docker container.

I tried running the database in differents container, I deploy my app to a Vercel server using railway database and I even tried fetching that data using a different package (node-postgres to be exactly).

I expect the page to retrieve fresh data every time I call the API endpoint, so if I add a new meal from the administrator, I can see that meal when I visit clients side.

Diego Saravia
  • 162
  • 11

1 Answers1

0

react-query will cache the result, unless the cache is invalidated.

Waiting for queries to become stale before they are fetched again doesn't always work, especially when you know for a fact that a query's data is out of date because of something the user has done. For that purpose, the QueryClient has an invalidateQueries method that lets you intelligently mark queries as stale and potentially refetch them too!

https://tanstack.com/query/v4/docs/react/guides/query-invalidation

You can invalidate the cache using:

import { useQueryClient } from '@tanstack/react-query'

const queryClient = useQueryClient()

queryClient.invalidateQueries({ queryKey: ["categoria", "comida"] })

You can invalidate it after you make the call to POST /api/comidas and create a meal.


On a side note, I notice that you are using v3 or lower of react-query. Better to update to latest stable v5 version.

Robin Thomas
  • 1,317
  • 8
  • 15