What is the syntax for typing the router instance in Next.js?

I'm working on a password reset request form in my Next.js project. Here's the code I have:

"use client";

import * as React from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import * as z from "zod";

import { cn } from "@/lib/util";
import { forgotPasswordSchema } from "@/lib/validations/auth";
import { buttonVariants } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Icons } from "@/components/icons";
import { useRouter } from "next/navigation";
import { requestPasswordReset } from "@/lib/request-password-reset";

export type FormData = z.infer<typeof forgotPasswordSchema>;

export function RequestPasswordResetForm() {
  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<FormData>({ resolver: zodResolver(forgotPasswordSchema) });

  const [isLoading, setIsLoading] = React.useState<boolean>(false);
  const [error, setError] = React.useState<string | null>(null);

  const router = useRouter();

  async function onSubmit(submittedData: FormData) {
    await requestPasswordReset({
      submittedData,
      setError,
      setIsLoading,
      reset,
      router,
    });
  }

  return (
    <div>
      {error && (
        <p className="mb-5 text-sm text-red-500 animate-in fade-in-0 slide-in-from-left-1">
          {error}
        </p>
      )}
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="grid gap-6">
          <div className="grid gap-1">
            <Label htmlFor="email">Email</Label>
            <Input
              id="email"
              type="email"
              placeholder="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="224c434f4762475a434f524e470c414d4f">[email protected]</a>"
              autoCapitalize="none"
              autoComplete="email"
              autoCorrect="off"
              disabled={isLoading}
              {...register("email")}
            />
            {errors.email && (
              <p className="px-1 text-xs text-red-600 animate-in fade-in-0 slide-in-from-left-1">
                {errors.email.message}
              </p>
            )}
          </div>
          <button className={cn(buttonVariants())} disabled={isLoading}>
            {isLoading && (
              <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
            )}
            Request password reset
          </button>
        </div>
      </form>
    </div>
  );
}

In the onSubmit handler, I call the requestPasswordReset() function, which includes router as an argument.

Here's the code for the requestPasswordReset() function:

import type { FormData } from "@/components/request-password-reset-form";

const RESPONSE_MESSAGES = {
  USER_NOT_FOUND: "User not found",
  EMAIL_NOT_VERIFIED: "User not registered",
  PASSWORD_RESET_LINK_SENT: "Password reset link sent",
  REQUEST_PASSWORD_RESET_FAILURE:
    "Password reset request failed. Please try again.",
};

interface RequestPasswordResetProps {
  submittedData: FormData;
  setError: React.Dispatch<React.SetStateAction<string | null>>;
  reset: () => void;
  setIsLoading: React.Dispatch<React.SetStateAction<boolean>>;
  router: any;
}

export async function requestPasswordReset({
  submittedData,
  setError,
  reset,
  setIsLoading,
  router,
}: RequestPasswordResetProps) {
  setIsLoading(true);
  setError(null);

  try {
    // Attempt to reset the user password
    const resetResponse = await fetch("/api/request-password-reset", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(submittedData),
    });

    // Reset failed
    if (!resetResponse.ok) {
      throw new Error(RESPONSE_MESSAGES.PASSWORD_RESET_FAILURE);
    }

    const resetResponseData = await resetResponse.json();

    // Handle different server responses
    if (resetResponseData.message === RESPONSE_MESSAGES.USER_NOT_FOUND) {
      setError(RESPONSE_MESSAGES.USER_NOT_FOUND);
      reset();
      return;
    }

    if (resetResponseData.message === RESPONSE_MESSAGES.EMAIL_NOT_VERIFIED) {
      setError(RESPONSE_MESSAGES.EMAIL_NOT_VERIFIED);
      reset();
      return;
    }
  } catch (error) {
    setError((error as Error).message);
  } finally {
    setIsLoading(false);
  }
}

Inside the RequestPasswordResetProps, I used router typed as any. What would be the proper way to annotate the router instance?

Thank you!

Answer №1

If you change the router to NextRouter, it seems like you're not actually using that router parameter, so could you just delete it altogether?

You can check out the type information in Nextjs official documentation here, but you might also be able to find it in your code editor like VSCode by hovering over it (maybe with some extensions).

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

Displaying the product price in a component header in Next.js when clicking on the product

I am relatively new to Next.js (React) and facing a challenge. I have created two components, header.tsx and product.tsx. These are being called in the file stepperLine.tsx under the "components" folder. My goal is to display the price of the product in th ...

Adjust the input width dynamically in Angular

Looking to dynamically adjust the width of an input field and ensure that the suffix "meters (m)" sticks close to the entered number. Additionally, I want to pass a specific value to the input using `value="something"`, which then should expand the input w ...

Advantages of optimizing NodeJS/TypeScript application by bundling it with webpack

Currently, I am working on a Node/Express application and I am interested in incorporating the most recent technologies. This includes using TypeScript with node/Express along with webpack. I have a question: What advantages come with utilizing webpack t ...

Encountering Problem **Issue: Invalid hook call. Hooks are intended to be used only within the body of a function component. **

i am facing an issue with Material UI in my ReactJS app. Without the below code (Component), my app works fine, but when I try to use it, I encounter an error: Error: Invalid hook call. Hooks can only be called inside of the body of a function component.. ...

Guide on integrating Socket.io into Next.js App Router

Struggling with Implementing Nextjs 13 App Router and Socket.io I've replicated everything, but I'm facing an issue with the socketio.ts file Check out the code on codesandbox.io socketio.ts File: import { NextApiRequest } from "next" ...

Sorting JSON arrays in Typescript or Angular with a custom order

Is there a way to properly sort a JSON array in Angular? Here is the array for reference: {"title":"DEASDFS","Id":11}, {"title":"AASDBSC","Id":2}, {"title":"JDADKL","Id":6}, {"title":"MDASDNO","Id":3}, {"title":"GHFASDI","Id":15}, {"title":"HASDFAI","Id": ...

Encountering an issue with TypeScript error code TS2322 when trying to assign a className to the @

Encountering a typescript error when trying to apply a className to a Box element. Interestingly, the same code works on other developers' machines with almost identical configurations. Current dependencies: "@material-ui/core": "4.11. ...

I am having trouble getting Angular 6 to work with lowdb

I am currently in the process of developing an Electron app with Angular 6, utilizing lowdb as a local database. This is all very new to me and I am learning through trial and error. However, I seem to be encountering difficulty resolving the following er ...

The type 'NextApiRequest' lacks the following attributes compared to type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'

An error has been identified in the code for a Next.js project below. The error message reads: Argument of type 'NextApiRequest' is not assignable to parameter of type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any ...

Svelte with Typescript: Uncovering the Types of Props

Issue: I am trying to create a function that can take a component as the first argument and its props as the second argument in a generic manner import Modal from "./Modal.svelte"; function openModal(component: typeof Modal, componentProps: ...

A keyboard is pressing on tabs and navigating through the app's contents in Ionic 3 on an Android device

I'm currently working on an IONIC 3 app and facing a challenge. When I tap on the ion search and the Keyboard pops up in ANDROID, it disrupts the layout by pushing all the content around. Original screen: Keyboard mode active: Things I've tri ...

Can getServerSideProps be adjusted to avoid triggering a complete page reload after the first load?

My server-rendered next.js app consists of a 3-page checkout flow. The first page involves fetching setup data like label translations and basket items within the getServerSideProps function, as shown below: UserDetails.js import React from 'react&apo ...

Harnessing the power of Ant Design's theme variables within the realm of emotion styling

I am currently working with Antd and emotion within a Next.js project. I want to access the Antd theme variables (which are written in Less) from within a component. Here is an example of what I would like to achieve: const StyledButton = styled(Button)` ...

Incorporating a parameter into a <div> only when the parameter holds a value

Being new to web development, I have a rather basic query. If the datainfo prop variable is not empty, I'd like to include a data attribute in the div tag. <div style={{height: props.height - handleHeight()}} data={datainfo ? datainfo : ""}> C ...

Vue Error: The method "reduce" is not a function

Currently implementing Vue.js with Typescript and aiming to utilize reduce for summing up the values of desktopCnt and mobileCnt from the deviceCount array to display their total numbers. The deviceCount array structure is as follows: [ { " ...

Removing API request in React.js

My approach: deleteSample = () => { this.sampleService .deleteCall(this.props.id) .then((response) => { window.location.reload(false); }) .catch((error) => { console.log ...

Unable to trigger dispatchEvent on an input element for the Tab key in Angular 5

In my pursuit of a solution to move from one input to another on the press of the Enter key, I came across various posts suggesting custom directives. However, I prefer a solution that works without having to implement a directive on every component. My a ...

What is the best way to create a nested item in the database?

Encountering various difficulties while attempting to create a new user with a nested related table in my database setup: model User { id Int @id @default(autoincrement()) username String @unique ...

I keep encountering the "Port 3000 is in use Error" whenever I try to restart npm run dev

Currently, I am working with nextjs on vscode. To initiate my server in localhost:3000, I use the command npm run dev. Then, to suspend the server, I use the keyboard shortcut ^Z. However, upon trying to restart the server using npm run dev, I encounter th ...

Frozen objects in Typescript 2 behave in a variety of ways depending on their shape

Let's say I'm working with an object whose inner structure is unknown to me because I didn't create it. For instance, I have a reference to an object called attributes that contains HTML attributes. I then made a shallow copy of it and froze ...