skip to Main Content

Hey Guys I am stuck could you please help.
I want to update query param on input change handler.

Points to be Noted

  1. I want the data with query params value parameter don’t suggest code with parent to child OR child to parent data transfer like Props or callback hanlder.
  2. As you update query params So they will be available instantly on Parent component with the functions you created.
  3. If there are more query parameter, only value query parameter shoudl change other query params shoudl remain same
Text Input Child Component:

const TextInputComp = () => {
    function onInputChange () {
    /* Logic to update only value query param not any other one if exist more query param */
    }
return (
    <input type="text" onChange={onInputChange} />
)
Parent Comp:

function ParentComp  ()  {
    const [valueQueryParam,setValueQueryParam] = useState() /* only value Query param should capture in useState  */

    useEffect(()=>{
    /* Your Logic to get value query Param fom URL with every time it changes  */
    },[/* Your Dependency */])

    return(
        <div>
            <TextInputComp />
            {valueQueryParam} your realtime query param text 
        </div>
    )
}

Please do not duplicate this question

2

Answers


  1. First of all, There are three main types of routing/navigation:

    • Hard Navigation
    • Soft Navigation
    • Shallow Navigation

    Hard Navigation would not be the worst choice to update the search param with since it reloads the entire page, skip the browser cache, destroy client-side state, etc…

    Still two types:

    1. Soft Navigation:
      Reloads as less as needed from the page and keep the cached/static files.

    Good to know: Refreshing the page onChange is not a good UX. You can use onBlur instead

    to push search param softly:

    import { useRouter, usePathname, useSearchParams } from "next/navigation";
    // ...
    const pathname = usePathname(); // let's get the pathname to make the component reusable - could be used anywhere in the project
    const router = useRouter();
    const currentSearchParams = useSearchParams();
    
    function onInputBlur(event) {
      // let's assume we want to push the `query` searchParam
      const query = event.target.value;
    
      const updatedSearchParams = new URLSearchParams(currentSearchParams.toString())
      updatedSearchParams.set("query", query)
    
      router.push(pathname + "?" + updatedSearchParams.toString())
    }
    
    1. Shallow Navigation
      This type changes the URL without reloading the page
    const currentSearchParams = useSearchParams();
    
    function onInputBlur(event) {
      const query = event.target.value;
    
      const updatedSearchParams = new URLSearchParams(currentSearchParams.toString())
      updatedSearchParams.set("query", query)
    
      window.history.pushState(null, "", "?" + updatedSearchParams.toString())
    }
    

    Keep away from the last option if you are using (a bit) old version of Next.js because it was introduced lately at 14.0.x and been enabled by default since 14.1.0. So, if anyone reads this answer and uses older next.js version this might not work as expected.

    Login or Signup to reply.
  2. This is exactly what nuqs was built to do (disclaimer: I’m the author).

    There are a couple of things to watch out for when connecting a high-frequency update source (text input, <input type="range"> slider) to the URL.

    One is that browsers rate-limit calls to the History API. Around 20 calls per second for Chrome and Firefox, but Safari has much lower limits (1000 calls per 30s). So you’ll want to throttle your updates.

    The issue of throttling is that a controlled input will become out of sync with its state, and will result to a janky experience.

    nuqs uses an internal state that updates as React.useState would, but defers and throttles updates to the URL in parallel, to reach eventual consistency.

    Your example would then look like this:

    'use client'
    
    import { useQueryState, parseAsString } from 'nuqs'
    
    const TextInputComp = () => {
      const [search, setSearch] = useQueryState(
        'search',
        parseAsString.withDefault('')
      )
      return (
        <input 
          type="text"
          value={search}
          onChange={e => setSearch(e.target.value || null)
          // null clears the query key if the input is empty
        />
    )
    

    Then your parent component (or anything else in the tree) can use the same hook to read the value:

    function ParentComp  ()  {
      const [search, setSearch] = useQueryState(
        'search',
        parseAsString.withDefault('')
      )
      return (
        <div>
          <TextInputComp />
          {search} your realtime query param text 
        </div>
      )
    }
    

    As a matter of fact, this exact use-case is showcased on the landing page demo: https://nuqs.47ng.com/?hello=AL+Faiz+Ahmed

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search