Next.js Discord

Discord Forum

When changing URL need to reset state

Unanswered
Basset Artésien Normand posted this in #help-forum
Open in Discord
Avatar
Basset Artésien NormandOP
This is my search component which is used within a Search page.
When browsing away from /search the text state does not seem to be resetting

'use client'

import React, { useState, useEffect, useRef } from 'react'
import { MagnifyingGlassIcon } from '@heroicons/react/20/solid'
import { useDebounce } from '@web/app/utils/'
import { useRouter, useSearchParams, usePathname } from 'next/navigation'

// TODO fix on button press

function Search() {
  const searchParams = useSearchParams()
  
  const search = searchParams.get('query')
  const initialRender = useRef(true)

  const [text, setText] = useState(search)

  const query = useDebounce(text, 750)
  const router = useRouter()

  useEffect(() => {
    setText(search)
  }, [search])

  useEffect(() => {
    
    if (initialRender.current) {
      initialRender.current = false
      return
    }

    if (query) {
      router.push(`/search?query=${query}`)
    }
  }, [query])

  return (
    <search className="flex flex-row items-center justify-center text-gray-600 px-2 py-3 border-b-[1px] border-zinc-600 md:border-0 ">
      <input
        className="border-2 border-gray-300 bg-white px-5 pr-16 rounded-full text-sm focus:outline-none md:h-8 h-10"
        type="search"
        name="search"
        placeholder="Search"
        onChange={(e) => setText(e.target.value)}
      />
      <MagnifyingGlassIcon className="w-5 h-5 text-zinc-500 relative right-10" />
    </search>
  )
}

export default Search

21 Replies

Avatar
Basset Artésien NormandOP
Image
Avatar
you may need to pass a key to the input.

here's a different implementation you can check that doesn't even require state

https://github.com/dayoawobeku/album-colors-app/blob/82aa110459ac62a6509885c3f246a54f6c7fe810/src/components/nav.tsx
Avatar
Basset Artésien NormandOP
looking now
Avatar
Milkfish
Easiest way is to use the pathname in the key - should reset the component when you navigate away (but beware, also rerenders on every pathname change as well)
Avatar
Basset Artésien NormandOP
What is the best approach here?
the whole page?
Avatar
Milkfish
something like
const pathname = usePathname();
<Search key={search-component-${pathname}}>
You could alternatively do something like:
const isSearchPage = pathname == '/search'
useEffect(() => { setText("") }, [isSearchPage])
Avatar
Basset Artésien NormandOP
this wont re-render?
Avatar
Milkfish
which one, key or the useeffect?
Avatar
Basset Artésien NormandOP
i know the useEffect will
not fully sure how the key works
export default function NavBar() {
  return (
    <header className="flex items-center justify-between dark:bg-zinc-800">
      <FilmIcon className="h-7 w-7 text-slate-200 m-2" />

      <input className="side-menu" type="checkbox" id="side-menu" />
      <label className="hamb" htmlFor="side-menu">
        <span className="hamb-line"></span>
      </label>

      <nav className="nav">
        <Search />
        <Navigation navItems={navItems} />
      </nav>
    </header>
  )
}

this is where search is implemented
which in turn is in the root layout:
import Navbar from '@web/app/ui/main/Navbar'

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div className="grid grid-rows-[50px_1fr] w-screen h-screen overflow-hidden">
      <Navbar />
      <main className="dark:bg-zinc-700 overflow-y-scroll">{children}</main>
    </div>
  )
}
Avatar
Milkfish
useEffect is arguably the most efficient method, and yes will cause rerender - but your component is already rerendering everytime there is a change because your using the usePathname, useSearchParams hooks
Avatar
Basset Artésien NormandOP
hm the useEffect does not seem to work
Avatar
Basset Artésien NormandOP
man im dumb. dont i just need value={text || ''} in the JSX