You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
  )
}

逻辑说明

  1. 初始状态同步:通过useSearchParams读取URL中的search参数,作为表单默认值,确保页面加载时两者状态一致
  2. 实时URL更新:用watch监听表单字段变化,在useEffect中构造新参数对象,通过router.replace修改URL。该方法不会触发页面重渲染,仅更新当前历史记录
  3. 空值处理:搜索框为空时,从URL中移除search参数,保持URL整洁
  4. 表单值绑定:在Controller的渲染回调中传入value属性,确保输入框值与表单状态完全同步

内容的提问来源于stack exchange,提问作者Luigi Cleffi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 06:35:27