update the query params of the page using a input in NextJS (App Router) – Javascript

by
Ali Hasan
javascript next.js next.js13 reactjs

Quick Fix: In NextJS (App Router) you can leverage the usePathname, useSearchParams, and useRouter hooks to update query parameters based on user input. Using the handleInputChange function, capture the input changes and store them in the searchQuery state. Call the updateSearchQuery function to update the URL query string with the new values using router.push.

The Problem:

In a Next.js (App Router) application, there’s a need to dynamically update query parameters based on user input using the onChange event in real time. The issue is that, upon entering text, the query parameters are updated first, and only after a brief delay does the input value get updated. The goal is to achieve simultaneous synchronization between the input value and the query parameters.

The Solutions:

Solution 1: Implementing Real-Time Synchronization between Input Value and Query Parameters

To achieve real-time synchronization between the input value and query parameters, we can utilize the useState, useEffect, and useRouter hooks. The following steps outline the solution:

  1. Create a State Variable for the Search Query:

    • Start by creating a React state variable called searchQuery to hold the current state of the search query.
    • Use the useState hook to initialize this state variable with an initial object that represents the default search criteria.
  2. Handle Input Changes:

    • Define an event handler function called handleInputChange. This function will handle changes to the input field.
    • Inside this function, extract the name and value from the event target.
    • Update the state variable searchQuery with the updated values using the setSearchQuery function.
  3. Update Search Query Parameters:

    • Define another function called updateSearchQuery. This function will be responsible for updating the query parameters in the URL.
    • Inside this function, create a new URLSearchParams object and use it to set, delete, or update query parameters based on the values in the searchQuery state variable.
    • Additionally, set the page parameter to ‘1’ to ensure the results start from the first page.
    • Finally, construct the updated query string and path, and use the useRouter hook to push the updated path to the URL.
  4. Render the Input Field:

    • In the render method of your component, use the value property of the input field to bind the current searchQuery.name value to the input field.
    • Attach the handleInputChange function as the onChange handler to the input field.

With this solution, you can now dynamically update both the query parameters in the URL and the value of the input field in real-time, providing a seamless user experience.

Solution: 2 Making the Input Controlled

To ensure real-time synchronization between the input value and the query parameters, it’s recommended to make the input a controlled component by maintaining its value in a state.

Here’s how you can achieve this:

  1. Initialize a State for the Search Parameter:
const [search, setSearch] = useState(value);
  1. Add an Event Listener to Update the State:

Attach an event listener, such as onkeydown or oninput, to the input element to capture user input and update the search state accordingly.

const changeHandler = (e) => {
    const { value } = e.target;
    setSearch(value);
};
  1. Update the Query Parameters in useEffect:

Use the useEffect hook to update the query parameters whenever the search state changes.

useEffect(() => {
    const params = new URLSearchParams(searchParams);
    params.set('name', search);
    params.set('page', 1);
    router.push(`${pathname}?${params.toString()}`);
}, [search]);

With this approach, the input value and the query parameters will be synchronized in real time, ensuring that the user’s input is reflected accurately in the URL.

\n

Solution 3: Using history.replaceState()

\n

This solution is a fully working client component implemented in Next14 App Router.

import { usePathname, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";

const Page = () => {
    const searchParams = useSearchParams();
    const params = new URLSearchParams(searchParams);
    const pathname = usePathname();

    // Store name and url state in a variable
    const [name, setName] = useState("");
    const [urlState, setUrlState] = useState("");

  // Implementation of `setParams` function
    const setParams = (key, value) => {
    params.set(key, value.toString());
    };

    // useEffect to set the name and page params on pageload and when the name from the input changes
    useEffect(() => {
    console.log(name);
    setParams("name", name);
    setParams("page", 1);
    history.replaceState(null, "", `${pathname}?${params.toString()}`);
    }, [name]);

    // Modified handlefilter function to set the name state
    const handleFilter = (e) => {
    const { name: key, value } = e.target;
    setName(value);
    };

    // Component
    return (
    <input
        type="text"
        className="form-control"
        placeholder="Name of the user"
        id="name"
        name="name"
        value={name}
        onChange={handleFilter}
    />
    );
};

export default Page;


This solution utilizes `history.replaceState()` to update the query parameters without causing a full page reload, ensuring real-time synchronization between the input value and the query parameters. It also handles Safari and iOS specific issues related to frequent state changes. This approach is considered a viable alternative until shallow routing is officially implemented in App Router.

Q&A

What alternatives are available for updating the query params in Next.js (App Router) along with real-time synchronization with the input value?

Consider using the history.replaceState() method instead, as it provides a more stable solution with fewer caveats.

How do I keep the input value and query parameters in sync in Next.js App Router?

Use a state variable to store the search parameter and update it using a useEffect hook.

Is there a way to avoid the brief delay between updating the query parameters and the input value in Next.js App Router?

Yes, you can use the history.replaceState() method to update the URL without causing a full page reload, thus eliminating the delay.

Video Explanation:

The following video, titled "Build a Search Bar with Next.js and Prisma (Search API endpoint ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

... Next.js application using Prisma. We'll look at how to add search query params to the URL, and use the search params to make a GET request ...