我有一组路由如下:
{
path: '/things',
element: <MainLayout />,
children: [
{
path: 'search',
element: <MainSearch />,
},
{
path: 'search/:thingId',
element: <ThingLayout />,
},
{
path: '',
element: <Navigate to="search" replace />,
},
],
},
其中的想法是,你在MainSearch上搜索一些东西,得到结果,点击它,然后进入该东西的/things/search/:thingId
页面。
然而,ThingLayout也有一个选项卡范例,它是由搜索参数和用户在该组件中单击选项卡来设置的。
精简布局.tsx
import { useParams, useSearchParams } from 'react-router-dom';
const ThingLayout = () => {
const [searchParams, setSearchParams] = useSearchParams();
const activeTab = searchParams.get('tab');
// When the user first comes here from general search route,
// set the default tab
useEffect(() => {
if (!activeTab) {
setSearchParams({ tab: DEFAULT_TAB });
}
}, []);
// ...
}
我的问题是,我需要(我相信(通用的/search/:thingId
路由,以便我的所有各种/search/:thingId?tab=someTab
路由都解析到此组件,然后该组件有代码来检查通过searchParams
设置了哪个选项卡,然后呈现正确的子组件,但如果用户按下后退按钮,URL将变为/search/:thingId
,然后立即返回/search/:thingId?tab=defaultTab
。我尝试使用navigate
而不是setSearchParams
来更改URL:
import { useNavigate } from 'react-router-dom';
// ...
const navigate = useNavigate();
navigate(`?tab=${DEFAULT_INVENTORY_PARTS_TAB}`)
但我遇到了同样的问题:当来自搜索时,首先URL将是/search/:thingId
,然后它将变成?tab=defaultTab
。
我搜索了react router文档,也查看了许多stackoverflow问题,现在我在想,也许我只是遵循了一个糟糕的模式?我的选项卡导航方法是否与";右";React Router的使用方法?如何将一般的:id
路由与我操纵的searchParams
路由相结合?
我的react路由器版本是"react-router-dom": "^6.2.1"
setSearchParams
的工作原理类似于navigate
函数,但仅适用于URL queryString。它接受一个与navigate
类型参数相同的选项对象。
declare function useSearchParams( defaultInit?: URLSearchParamsInit ): [URLSearchParams, SetURLSearchParams]; type ParamKeyValuePair = [string, string]; type URLSearchParamsInit = | string | ParamKeyValuePair[] | Record<string, string | string[]> | URLSearchParams; type SetURLSearchParams = ( nextInit?: URLSearchParamsInit, navigateOpts?: : { replace?: boolean; state?: any } ) => void;
传递一个navigateOpts
对象,该对象将导航类型设置为重定向。
import { useParams, useSearchParams } from 'react-router-dom';
const ThingLayout = () => {
const [searchParams, setSearchParams] = useSearchParams();
const activeTab = searchParams.get('tab');
// When the user first comes here from general search route,
// set the default tab
useEffect(() => {
if (!activeTab) {
searchParams.set("tab", DEFAULT_TAB);
setSearchParams(searchParams, { replace: true });
}
}, []);
// ...
}
答案是使用react-router-dom
的useNavigate
钩子提供的navigate
函数来替换历史中的当前项,该钩子有一个可以传递给它的replace
参数。
因此,我的代码检查是否选择了选项卡,如果没有,则设置搜索参数,现在navigate
s为具有正确搜索参数集的URL,而不是直接且仅设置搜索参数。
import { useParams, useSearchParams } from 'react-router-dom';
const ThingLayout = () => {
const [searchParams, setSearchParams] = useSearchParams();
const activeTab = searchParams.get('tab');
// When the user first comes here from general search route,
// set the default tab
useEffect(() => {
if (!activeTab) {
setSearchParams({ tab: DEFAULT_TAB });
}
}, []);
// ...
}
成为
import { useSearchParams, useNavigate } from 'react-router-dom';
const ThingLayout = () => {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const activeTab = searchParams.get('tab');
// When the user first comes here from general search route,
// set the default tab
useEffect(() => {
if (!activeTab) {
navigate(`?tab=${DEFAULT_TAB}`, {replace: true});
}
}, []);
// ...
}