Next.js最新版本实现输入时URL追加查询参数(无重渲染)
解决方案
要实现输入内容实时同步到URL查询参数且不触发页面重渲染,你需要调整以下核心逻辑:
关键修改点
- 用
useSearchParams获取当前URL的查询参数,作为表单初始值,保证URL与表单状态一致 - 监听表单值变化,通过
router.replace更新URL(避免冗余历史记录),构造新的URLSearchParams来维护参数 - 同步表单输入值与URL参数,确保双向一致
- 移除不必要的
isClient状态判断('use client'组件已明确为客户端渲染)
完整修改代码
'use client' import { MagnifyingGlassIcon } from '@heroicons/react/24/solid' import * as Form from '@radix-ui/react-form' import { Flex } from '@radix-ui/themes' import { useRouter, useSearchParams } from 'next/navigation' import { useEffect } from 'react' import { Controller, Resolver, useForm } from 'react-hook-form' type FormValues = { search: string } const resolver: Resolver<FormValues> = async (values) => { return { values: values.search ? values : {}, errors: values.search ? {} : { search: { type: 'required', message: 'This is required.', }, }, } } export const Search: React.FC = () => { const router = useRouter() const searchParams = useSearchParams() // 从URL读取初始搜索值 const initialSearchValue = searchParams.get('search') || '' const { control, watch, formState: { errors }, } = useForm<FormValues>({ resolver, defaultValues: { search: initialSearchValue }, }) // 监听搜索值变化,实时更新URL const searchValue = watch('search') useEffect(() => { const newParams = new URLSearchParams(searchParams) if (searchValue) { newParams.set('search', searchValue) } else { newParams.delete('search') } // 使用replace更新URL,不会触发页面重渲染 router.replace(`?${newParams.toString()}`, { scroll: false }) }, [searchValue, searchParams, router]) return ( <Form.Root> <Form.Field name="search"> <Flex width="100%"> <MagnifyingGlassIcon className="h-8 p-2 text-white bg-zinc-800 rounded-l-sm duration-100 hover:scale-105" /> <Form.Control asChild> <Controller control={control} name="search" render={({ field: { onChange, value } }) => ( <input placeholder="Search a project..." type="search" className="outline-none border-b border-gray-200 px-4 text-sm focus-within:ring-1 focus-within:ring-blue-400 hover:ring-1 hover:ring-blue-600 focus-within:shadow-md focus-within:shadow-slate-300 rounded-r-lg " onChange={onChange} value={value} /> )} /> </Form.Control> </Flex> {errors.search && ( <Form.Message className="text-red-500 text-sm mt-1"> {errors.search.message} </Form.Message> )} </Form.Field> </Form.Root> ) }
逻辑说明
- 初始状态同步:通过
useSearchParams读取URL中的search参数,作为表单默认值,确保页面加载时两者状态一致 - 实时URL更新:用
watch监听表单字段变化,在useEffect中构造新参数对象,通过router.replace修改URL。该方法不会触发页面重渲染,仅更新当前历史记录 - 空值处理:搜索框为空时,从URL中移除
search参数,保持URL整洁 - 表单值绑定:在
Controller的渲染回调中传入value属性,确保输入框值与表单状态完全同步
内容的提问来源于stack exchange,提问作者Luigi Cleffi
相关产品推荐
相关产品推荐

