繁体   English   中英

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

[英]How to combine react-router-dom's setSearchParams with route that has a param in a way that allows correct back button usage?

我有一组如下所示的路线:

{
    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

我已经搜索了反应路由器文档,并查看了很多 stackoverflow 问题,我现在在想也许我只是遵循了一个不好的模式? 我的标签导航方法是否与使用 React Router 的“正确”方式兼容? 如何将一般:id路线与我操纵的searchParams路线结合起来?

我的反应路由器版本是"react-router-dom": "^6.2.1"

setSearchParams的工作方式类似于navigate function,但仅适用于 URL 查询字符串。 它需要一个选项 object ,它与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 object。

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 function ,它有一个可以传递给它的replace参数,来替换历史中的当前项目。

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

// ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM