Next.js Discord

Discord Forum

Hydration Error in the new Learn Nextjs course

Unanswered
Mrigal carp posted this in #help-forum
Open in Discord
Mrigal carpOP
Hi!

Im new to NextJS and I'm currently moving through the next course. I'm currently getting:

Unhandled Runtime Error
Error: Hydration failed because the initial UI does not match what was rendered on the server.

Warning: Did not expect server HTML to contain a <div> in <div>.

See more info here: https://nextjs.org/docs/messages/react-hydration-error



The hydration error is not there if I remove the placeholder entirely from the <input/> inside <Search/>. Any suggestions on how to fix?

2 Replies

Mrigal carpOP
On my Search-component.

Im using it in app/dashboard/invoices/page.tsx like so :


const Page = ({ searchParams }: Props) => { const query = searchParams?.query || ''; const currentPage = Number(searchParams?.page) || 1; const totalPages = fetchInvoicesPages(query); return ( <div className="w-full"> <div className="flex w-full items-center justify-between"> <h1 className={${lusitana.className} text-2xl}>Invoices</h1> </div> <div className="mt-4 flex items-center justify-between gap-2 md:mt-8"> <Search placeholder="Search invoices..."/> <CreateInvoice /> </div> <Suspense key={query + currentPage} fallback={<InvoicesTableSkeleton />}> <Table query={query} currentPage={currentPage} /> </Suspense> <div className="mt-5 flex w-full justify-center"> {/* <Pagination totalPages={totalPages} /> */} </div> </div> ) };
export default function Search({ placeholder }: { placeholder: string }) { const searchParams = useSearchParams(); const pathname = usePathname(); const { replace } = useRouter(); const handleSearch = useDebouncedCallback((term: string) => { const params = new URLSearchParams(searchParams) if (term) { params.set('query', term); } else { params.delete('query'); } replace(${pathname}?${params.toString()}); }, 300); return ( <div className="relative flex flex-1 flex-shrink-0"> <label htmlFor="search" className="sr-only"> Search </label> <input id='search' className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500" placeholder={placeholder} onChange={(e) => { handleSearch(e.target.value); }} defaultValue={searchParams.get('query')?.toString()} /> <MagnifyingGlassIcon className="absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" /> </div> ); }