使用 react-router v6 和 useNavigate

时间:2021-02-03 09:55:07

标签: javascript reactjs react-router

我正在尝试弄清楚如何使用 useNavigate 挂钩来导航/重定向用户并更新查询参数(如果有)。

我创建了一个自定义的 useNavigateParams 钩子,我从几个不同的 SO 答案中改编了它,它看起来像这样:

import { generatePath, ParamKeyValuePair, useNavigate } from 'react-router-dom';
import { getSearchParams, isObjectEmpty } from 'src/utils';

type TUseNavigateParams = {
    uri: string;
    params?: Record<string, unknown>;
};
export default function useNavigateParams() {
    const navigate = useNavigate();

    return ({ uri, params = {} }: TUseNavigateParams) => {
        let path = uri;
        if (!isObjectEmpty(params)) {
            path += generatePath('?:queryString', {
                uri,
                queryString: getSearchParams(Object.entries(params) as ParamKeyValuePair[]),
            });
        }

        console.log('decoded', decodeURIComponent(path));

        navigate(path);
    };
}

const getSearchParams = (params: ParamKeyValuePair[]) => {
    let searchParams = '';
    params.forEach((param, index) => {
        const localDestructured = Object.entries(param[1]);
        console.log('localDestructured', localDestructured);
        searchParams += createSearchParams({
            [param[0]]: JSON.stringify({ [localDestructured[0][0]]: localDestructured[0][1] }),
        });
    });

    return createSearchParams(searchParams).toString();
};

这里的想法是,我基本上会在整个项目中始终使用 useNavigateParams,而不是 useNavigate

我的问题如下。像下面这样简单的东西就可以正常工作:

const uri = 'myPath'
const filter = 'active'
const params = { filter: { status: filter } }

navigate({
    uri,
    params,
})

这将打印,

myPath?filter={"status":"active"}

但是做类似的事情,

const uri = 'myPath'
const filter = 'active'
const params = { filter: { status: filter, hello: 'world' } }

navigate({
    uri,
    params,
})

不会打印,

myPath?filter={"status":"active", "hello":"world"}

我知道我可以添加另一个 forEach 或找出一些笨拙的方法,但它看起来如此庞大,而且它实际上无法重复使用/动态。

我希望能够传递某种参数,例如,

const uri = 'myPath'
const filter = 'active'
const params = { filter: { status: filter, hello: 'world' }, foo: 'bar', baz: { node: 'leaf' } }

navigate({
    uri,
    params,
})

并期望输出为:

myPath?filter={"status":"active", "hello":"world"}&foo=bar&baz={"node":"leaf"}

是否有更简洁、更可靠的方法来实现这样的结果?

1 个答案:

答案 0 :(得分:0)

我已经在使用 axios,所以我最终使用了 getUri

import axios from 'axios';
import { useNavigate } from 'react-router-dom';

type TUseNavigateParams = {
    uri: string;
    params?: Record<string, unknown>;
};
export default function useNavigateParams() {
    const navigate = useNavigate();

    return ({ uri, params = {} }: TUseNavigateParams) => {
        const path = axios.getUri({ url: uri, params });

        navigate(path);
    };
}