浏览客户端时在NextJS中持久化查询字符串参数

brtdzjyr  于 2023-11-18  发布在  其他
关注(0)|答案(5)|浏览(99)

nextjsnext-routes配合使用时,在页面之间导航时是否可以保留URL的查询字符串?我有一个广告活动正在运行,我需要在浏览页面时保留它,以便进行历史原因和跟踪。
我不能把它塞进Redux商店,或者localhost,sessionstorage等,它必须留在URL中。
我尝试了以下方法:

import { Router } from 'routes';

Router.events.on('routeChangeStart', (url: string) => {
  if (Router.query && Router.router.pathname !== url) {
    const href = `${url}${Object.keys(Router.query).reduce(
      (carry: string, key: string) => {
        carry += `${carry === '' ? '?' : '&'}${key}=${Router.query[key]}`;
                return carry;
    },'')}`;

    Router.pushRoute(href, Router.router.pathname, { shallow: true });
  }
});

字符串
routes.js文件导出next-routes

const nextRoutes = require('next-routes');  
const routes = (module.exports = nextRoutes());


这里发生的情况是,URL被正确推送,查询字符串持续存在,但只是短暂的 Flink 。它立即将原始url推回Router,我失去了查询字符串参数。
我已经尝试了其他几种变体,但不幸的是,我找不到正确的实现。
任何帮助都是感激不尽的。

0qx6xfy6

0qx6xfy61#

经过一番搜索,我设法得到了我想要的结果,如下所示:

const customRouter = (module.exports = nextRoutes());

customRouter.Router.pushRouteWithQuery = function(route, params, options) {
    if(!params || !Object.keys(params).length) {
        const routeWithParams = QueryStringHelper.generateUrlWithQueryString(route, customRouter.Router.router.query);
        customRouter.Router.pushRoute(routeWithParams, params, options);
    } else {
        const filteredParams = QueryStringHelper.filterAllowedParams(customRouter.Router.router.query);
        const allParams = {
            ...filteredParams,
            ...params
        };

        customRouter.Router.pushRoute(route, allParams, options);
    }
}

字符串
然后,我将使用我新创建的方法重定向到另一个带有所需查询字符串的页面:

import { Router } from 'my/module'

Router.pushRouteWithQuery('/home');


最后是QueryStringHelper

module.exports = {
    generateUrlWithQueryString,
    getAllowedParams,
    prepareParamsAsQueryString,
    filterAllowedParams
}

function getAllowedParams() {
    const allowedParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'mid', 'gclid', 'source'];

    return allowedParams;
}

function prepareParamsAsQueryString() {
    const params = getAllowedParams();
    let paramsLikeQueryString = [];

    for (let index = 0; index < params.length; index++) {
        const param = params[index];

        paramsLikeQueryString.push(`${param}=:${param}?`);
    }

    return paramsLikeQueryString.join('&');
}

function generateUrlWithQueryString(url, params) {
    if(Object.keys(params).length) {
        const filteredParams = filterAllowedParams(params);

        if (Object.keys(filteredParams).length) {
            if(url[0] != '/')
                url = `/${url}`;

            return `${url}?${serialize(filteredParams)}`;
        }

        return url;
    }

    return url;
}

function filterAllowedParams(params) {
    if(Object.keys(params).length) {
        const filteredParams = Object.keys(params)
            .filter(key => getAllowedParams().includes(key.toLowerCase()))
            .reduce((obj, key) => {
                obj[key] = params[key];
                return obj;
            }, {});

        return filteredParams;
    }

    return params;
}

// INTERNAL
function serialize(obj) {
    var str = [];
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        }
    }

    return str.join("&");
}

w3nuxt5m

w3nuxt5m2#

npm install query-string

个字符

pjngdqdw

pjngdqdw3#

帮助我们的是URLURLSearchParams API。
我们创建了一些小方法,在使用router.push时使用它们,这里是一个更改路由但持久化查询参数的示例:

/**
 *
 * @param currentPath the current asPath the user is on, eg /stuff/example/more-stuff?utm-campaing=test
 * @param newPath the new path we want to push to the router, eg /stuff/example/even-more-stuff
 * @returns the newPath with the query params from the existing path, eg /stuff/example/even-more-stuff?utm-campaing=test
 */
export const changeRouteKeepParams = (
  currentPath: string,
  newPath: string
): string => {
  const hasQueries = currentPath.indexOf('?');
  const searchQuery = hasQueries >= 0 ? currentPath.substring(hasQueries) : '';
  const params = new URLSearchParams(searchQuery);
  const paramsStr = params.toString() !== '' ? `?${params.toString()}` : '';
  return `${newPath}${paramsStr}`;
};

字符串

w8ntj3qf

w8ntj3qf4#

对于那些使用NextJS 13+和新的App路由器的人,你可以创建一个自定义钩子来 Package 标准的rooter钩子。下面是我是如何做到的:

import { NavigateOptions } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { useRouter, useSearchParams } from "next/navigation";

export interface CustomRouterOptions {
  preserveQuery: boolean;
}

export function useCustomRouter() {
  const router = useRouter();
  const searchParams = useSearchParams();

  const push = (href: string, routerOptions?: CustomRouterOptions, options?: NavigateOptions) => {
    // HACK: If relative URL given, stick the current host on the string passed to URL()
    // as the constructor throws an error if URL without a host is given
    const url = new URL(href.includes("http") ? href : window.location.host + href);
    if (routerOptions?.preserveQuery) {
      searchParams.forEach((val, key) => {
        url.searchParams.append(key, val);
      });
    }

    let urlString = url.toString();

    // If the href arg was relative, strip everything before the first '/' to
    // revert it back to a relative URL we can pass into the router.push() method
    if (!href.includes("http")) {
      urlString = urlString.substring(urlString.indexOf("/"));
    }

    router.push(urlString, options);
  };

  return { push };
}

字符串

iqjalb3h

iqjalb3h5#

我从URL中获取查询字符串,并将其长传递到我使用组件的任何地方。

import { useRouter } from "next/router";
import { useEffect, useState } from "react";

export const getUrlPathParams = (): string => {
  const [pathParams, setPathParams] = useState("");
  useEffect(() => {
    setPathParams(router?.asPath?.slice(router?.pathname?.length));
  });
  const router = useRouter();
  return pathParams;
};

字符串
一个在链接中使用它的例子。

<Link href={"/" + getUrlPathParams()}> Home </Link>


我做同样的事情,我的外部链接,使我的广告活动的作品。

相关问题