Tips for preventing duplicate data fetching in Next.js version 13

I am currently in need of retrieving information from the database, generating metadata, and displaying the page content. The current method I am using is as follows:

export const generateMetadata = async ({
  params: { questionSlug },
}: Props): Promise<Metadata> => {
  const sql = await connectToPostgres();

  const question = await findQuestion(sql, questionSlug);

  if (!question) {
    return {};
  }

  return {
    alternates: {
      canonical: `https://ray.run/questions/${question.slug}`,
    },
    title: question.question,
  };
};

const Page = async ({ params: { questionSlug } }: Props) => {
  const sql = await connectToPostgres();

  const question = await findQuestion(sql, questionSlug);

  if (!question) {
    return notFound();
  }

  // ...
};

However, this approach requires querying the database twice to render the same page.

Is there a more efficient way to retrieve data once and utilize it in both functions?

Answer №1

It may not be the most visually appealing solution, but the recommended approach is to utilize the cache function:

import { cache } from 'react';

const findQuestionWithCache = cache(async (questionSlug: string) => {
  const sql = await connectToPostgres();

  return await findQuestion(sql, questionSlug);
});

export const generateMetadata = async ({
  params: { questionSlug },
}: Props): Promise<Metadata> => {
  const question = await findQuestionWithCache(questionSlug);

  if (!question) {
    return notFound();
  }

  return {
    alternates: {
      canonical: `https://ray.run/questions/${question.slug}`,
    },
    title: question.question,
  };
};

const Page = async ({ params: { questionSlug } }: Props) => {
  const question = await findQuestionWithCache(questionSlug);

  if (!question) {
    return notFound();
  }

  // ...
};

The findQuestionWithCache function will only be executed once per request.

One drawback of this method is that the cache wrapped function cannot be used outside of React/Next.js. If you need to use the same function elsewhere in your codebase, you'll have to wrap it locally like demonstrated in the example above. However, if you're only using this function within your React.js code, you can simply wrap the original implementation without any additional steps.

Answer №2

When it comes to Next.js, fetch requests for generateMetadata are deduplicated, but there might be some uncertainties regarding your database connection. Explore the helpful information section for more details.

Answer №3

Here's a suggested approach: Embed the cache object at the top.


let cache = {};

export const generateMetadata = async ({
  params: { questionSlug },
}: Props): Promise<Metadata> => {
// Utilize this conditional statement to retrieve data from cache instead of making a server request.
if (cache) return cache;
  const sql = await connectToPostgres();

  const question = await findQuestion(sql, questionSlug);

  if (!question) {
    return {};
  }
  cache = question;
  return {
    alternates: {
      canonical: `https://ray.run/questions/${question.slug}`,
    },
    title: question.question,
  };
};

const Page = async ({ params: { questionSlug } }: Props) => {
  
  if (!cache) {
    await connectToPostgres();
    
    const question = await findQuestion(sql, questionSlug);
    if (!question) return notFound();
  }
  
  const response = cache;

  // ... utilize the response variable as cached data.
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular 16 routing not loading content

I configured the routes in Angular v16 and encountered a blank page issue with the login and register functionality. I suspect it has to do with routing, but after checking multiple times, I couldn't pinpoint the exact problem. Below are snippets of t ...

Custom server not required for optional dynamic routes in NextJS version 9.5.2

I am attempting to implement localized routes with an optional first parameter in the form of /lang?/../../, all without requiring a custom server. Starting from NextJS version 9.5, there is a new dynamic optional parameters feature that can be set up by c ...

What is the best way to switch a boolean state in React using TypeScript?

Hey there! I'm diving into the world of React and TypeScript. My goal is to toggle a boolean state (true/false) using a handler function. While I've come across solutions in ES6, I'm struggling to grasp how it can be implemented in TypeScri ...

What are the steps to ensure a successful deeplink integration on iOS with Ionic?

Recently, I was working on a hybrid mobile app for Android/iOS using Nuxt 3, TypeScript, and Ionic. The main purpose of the app is to serve as an online store. One important feature involves redirecting users to the epay Halyk website during the payment pr ...

Do you need to incorporate 'next-redux-wrapper' into a 'Next.js + Redux Toolkit' project if you are solely using 'static generation'?

I am currently in the process of developing a Next.js application using Redux Toolkit for managing state. My approach involves utilizing Static Generation through getStaticProps and getStaticPaths. My question is whether it is necessary to incorporate nex ...

When running jest unit tests, an error is thrown stating that includes() and toLowerCase are not functions

MyComponent.js contains both toLowerCase and includes methods on the props. However, when attempting to perform unit testing on MyComponent, I encounter an issue where the functions toLowerCase() and includes() are not recognized as valid. Within MyCompon ...

Angular 1.5 Karma unit test causes duplicate loading of ng-mock library

My current web app is built using Typescript 2.4.2 and compiled with the latest Webpack version (2.7.0). I am in the process of incorporating Karma tests utilizing Jasmine as the assertion library. Below is my karma configuration file: 'use strict& ...

Oh no! It seems like the build script is missing in the NPM

https://i.stack.imgur.com/el7zM.jpg npm ERR! missing script: build; I find it strange, what could be causing this issue? Any suggestions? I have included the fullstack error with the package.json. Please also review the build.sh code below. Fullstack err ...

Nested HTTP requests in Angular using RxJS: Triggering component update after completion of the first HTTP request

I have a requirement to make two http requests sequentially. The values retrieved from the first call will be used in the second call. Additionally, I need to update my component once the first http request is completed and also update it once the second ...

Is there a way to prevent IntelliJ from creating .js files when working with .ts source code?

Working on a mixed Java/Typescript project with Maven as the build tool, I utilize the frontend-maven-plugin to successfully build from the command line. However, I am encountering an issue with IntelliJ 2018.2 where it keeps transpiling .js files for my . ...

Combining Axios with repeated promises

I am facing an issue with a loop in my GET request on the axis, and I cannot figure out why. const [ state, setState ] = useState<any[]>([]); ids.forEach((id) => { getData(id) .then((smth: Map<string, any>[]) => getNeededData ...

Oops! Looks like there's an unexpected error with the module 'AppRoutingModule' that was declared in the 'AppModule'. Make sure to add a @Pipe/@Directive/@Component annotation

I am trying to create a ticket, but I encountered an error. I am currently stuck in this situation and receiving the following error message: Uncaught Error: Unexpected module 'AppRoutingModule' declared by the module 'AppModule'. Plea ...

Error in Directive: NgControl Provider Not Found

I encountered an issue with my Directive while attempting to inject 'NgControl' and received a 'No provider for NgControl' error. Here is the structure of my File Directory: app folder |--directives folder |--myDirec ...

Instructions for creating a function that can receive an array of objects containing a particular data type for the value associated with the key K

Seeking guidance on how to define a specific signature for a function that accepts an array of objects and 3 column names as input: function customFunction<T, K extends keyof T>( dataset: T[], propertyOne: K, propertyTwo: K, propertyThird: K ...

Tips for avoiding a form reload on onSubmit during unit testing with jasmine

I'm currently working on a unit test to ensure that a user can't submit a form until all fields have been filled out. The test itself is functioning correctly and passes, but the problem arises when the default behavior of form submission causes ...

When trying to access the "form" property of a form ElementRef, TypeScript throws an error

I've encountered an issue with accessing the validity of a form in my template: <form #heroForm="ngForm" (ngSubmit)="onSubmit()"> After adding it as a ViewChild in the controller: @ViewChild('heroForm') heroForm: ElementRef; Trying ...

Is there a way to determine the specific child property types of a custom Generic type extension?

I am looking to create a function that can retrieve a property from an extended generic type. Is this something achievable? Here is my attempt: interface Animal { readonly weight: {total: number} } interface Dog extends Animal { readonly weight: ...

Steps to configure Visual Studio Code to automatically open the original TypeScript file located in the "src" folder when a breakpoint is hit in a Node.js application

I am currently working on a CLI node application and using VSCode to debug it. Everything seems to be working fine, except for one annoyance: when I hit a breakpoint, VSCode opens the source map file instead of the actual TypeScript file located in my "src ...

Unit testing the error function within the subscribe method in Angular

I've been working on a unit test for the subscribe call, but I'm struggling to cover the error handling aspect of the subscribe method. The handleError function deals with statusCode=403 errors and other status codes. Any assistance would be grea ...

Certain Material-UI components appear to lack proper styling

I found a tutorial on how to incorporate material UI into my app at this link: https://mui.com/material-ui/getting-started However, I noticed that some components are not styled as expected and customizing the theme seems to have no effect... This is how ...