Next.js客户端组件表单数据传递至动态路由组件的问题解决
问题:Next.js useRouter跳转后query参数未生效
我有一个名为BookingBox.tsx的Next.js客户端组件,通过useEffect从JSON文件获取数据填充下拉选项,已在page.tsx中引入。现需将表单数据传递至动态路由[...slug]/process.tsx组件,尝试使用useRouter()跳转但query参数未生效,附上代码求助:
"use client" import React, { useState, useEffect } from 'react'; import Select from 'react-select'; // import router from 'next/router'; import { useRouter } from 'next/navigation'; interface ZRoutes { From: string; To: string; shuttle: number; sedan: number; van: number; minibus: number; coach: number; } export default function BookingBox() { const router = useRouter(); const [pickup, setPickup] = useState<any>(null); const [pickupdate, setPickupdate] = useState(""); const [passengers, setPassengers] = useState(""); const [dropoff, setDropoff] = useState<any>(null); const [myroutes, setMyRoutes] = useState<ZRoutes[]>([]); const handleSelectedPickup = (pickup: any) => { setPickup(pickup); }; const handleSelectedDropoff = (dropoff: any) => { setDropoff(dropoff); }; useEffect(() => { async function fetchData() { try { const response = await fetch('/zanzibar-airport-rates.json'); if (!response.ok) { throw new Error('Failed to fetch data'); } const data = await response.json(); setMyRoutes(data); } catch (error) { console.error(error); } } fetchData(); }, []); const myRouteOptions = myroutes.map((route) => ({ value: route?.To || '', label: route?.To || '', })); const handleFormSubmit = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData = { pickup: pickup?.value || "", dropoff: dropoff?.value || "", passengers: passengers, pickupdate: pickupdate, }; const formattedPickup = pickup?.value.replace(/%20|\s/g, '-'); const formattedDropoff = dropoff?.value.replace(/%20|\s/g, '-'); router.push({ pathname: '/${formattedPickup}/${formattedDropoff}`', query:formData }); }; return ( <div className="booking-area"> <div className="container"> <div className="booking-form"> <h4 className="booking-title">Book Your Airport Taxi</h4> <form onSubmit={handleFormSubmit}> <div className="row"> <div className="col-lg-3"> <div className="form-group"> <label>From</label> <Select options={myRouteOptions} value={pickup} onChange={handleSelectedPickup} /> <i className="far fa-location-dot" /> </div> </div> <div className="col-lg-3"> <div className="form-group"> <label>To</label> <Select options={myRouteOptions} value={dropoff} onChange={handleSelectedDropoff} /> <i className="far fa-location-dot" /> </div> </div> <div className="col-lg-2"> <div className="form-group"> <label>Passengers</label> <input type="number" className="form-control" placeholder="Passengers" name="Passengers" value={passengers} onChange={(e) => setPassengers(e.target.value)} /> <i className="far fa-user-tie" /> </div> </div> <div className="col-lg-2"> <div className="form-group"> <label>Pick Up Date</label> <input type="date" name="Pickupdate" className="form-control" placeholder="MM/DD/YY" value={pickupdate} onChange={(e) => setPickupdate(e.target.value)} /> </div> </div> <div className="col-lg-2 align-self-end"> <button className="theme-btn" name="booktaxibtn" type="submit"> Book Taxi <i className="fas fa-arrow-right" /> </button> </div> </div> </form> </div> </div> </div> ); }
问题分析与修复
核心问题
- 模板字符串语法错误:路径使用单引号包裹,导致
${formattedPickup}和${formattedDropoff}未被解析为变量,且末尾多了一个多余的反引号。 - App Router的useRouter不支持直接传query对象:
next/navigation中的useRouter.push()不接受query属性,需要手动将表单数据转换为URL查询字符串。
修复后的handleFormSubmit函数
const handleFormSubmit = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData = { pickup: pickup?.value || "", dropoff: dropoff?.value || "", passengers: passengers, pickupdate: pickupdate, }; const formattedPickup = pickup?.value.replace(/\s/g, '-'); const formattedDropoff = dropoff?.value.replace(/\s/g, '-'); // 将表单数据转为URL查询字符串 const searchParams = new URLSearchParams(formData); const queryString = searchParams.toString(); // 修正路径语法,确保匹配你的动态路由结构 // 假设目标路由是 /[pickup]/[dropoff]/process,若路由结构不同请自行调整 const targetPath = `/${formattedPickup}/${formattedDropoff}/process?${queryString}`; router.push(targetPath); };
额外说明
- 若你的动态路由是
app/process/[...slug]/page.tsx,则目标路径应改为/process/${formattedPickup}/${formattedDropoff}?${queryString},slug会捕获formattedPickup和formattedDropoff作为参数。 - 在
process.tsx中,可以通过useSearchParams()获取查询参数:"use client" import { useSearchParams } from 'next/navigation'; export default function ProcessPage() { const searchParams = useSearchParams(); const pickup = searchParams.get('pickup'); const dropoff = searchParams.get('dropoff'); const passengers = searchParams.get('passengers'); const pickupdate = searchParams.get('pickupdate'); // 使用参数进行后续处理 return <div>...</div>; }
内容的提问来源于stack exchange,提问作者zahor hassan
相关产品推荐
相关产品推荐

