如何将 react-router-dom 的 setSearchParams 与具有参数的路由相结合,以允许正确使用后退按钮?



我有一组路由如下:

{
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-domuseNavigate钩子提供的navigate函数来替换历史中的当前项,该钩子有一个可以传递给它的replace参数。

因此,我的代码检查是否选择了选项卡,如果没有,则设置搜索参数,现在navigates为具有正确搜索参数集的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});
}
}, []);
// ...
}

最新更新