Reactjs 导航客户端时在NextJS中保留查询字符串参数

Reactjs 导航客户端时在NextJS中保留查询字符串参数,reactjs,next.js,Reactjs,Next.js,将nextjs与next routes一起使用,在页面之间导航时是否可以保留URL的查询字符串?我有一个广告活动,我需要保留它,因为我浏览网页的历史原因和跟踪 我无法将其填充到Redux存储区、localhost、sessionstorage等中。它必须保留在URL中 我尝试了以下方法: import { Router } from 'routes'; Router.events.on('routeChangeStart', (url: string) => { if (Router

nextjs
next 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 });
  }
});
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);
    }
}
并且
routes.js
文件导出
next routes

const nextRoutes = require('next-routes');  
const routes = (module.exports = nextRoutes());
这里发生的事情是正确地推送了URL,并且查询字符串仍然存在,但只是短暂的一闪。它立即将原始的
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 });
  }
});
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("&");
}
module.exports={
带查询字符串的发电机,
getAllowedParams,
预处理,
过滤降低参数
}
函数getAllowedParams(){
const allowedParams=['utm_源'、'utm_中'、'utm_活动'、'utm_术语'、'utm_内容'、'mid'、'gclid'、'源'];
返回允许的参数;
}
函数prepareParamsQueryString(){
const params=getAllowedParams();
设paramsLikeQueryString=[];
for(让index=0;indexgetAllowedParams().includes(key.toLowerCase()))
.reduce((对象,键)=>{
obj[key]=参数[key];
返回obj;
}, {});
返回过滤器参数;
}
返回参数;
}
//内部的
函数序列化(obj){
var-str=[];
用于(obj中的var p){
if(对象hasOwnProperty(p)){
str.push(encodeURIComponent(p)+“=”+encodeURIComponent(obj[p]));
}
}
返回str.join(“&”);
}

我从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>
主页

我也在为我的外部链接做同样的事情,以使我的广告活动有效。

不幸的是,我认为一旦在next.js中启动路由(由
routeChangeStart
事件检测),您可以执行一些操作,但不能更改路由本身,这可能就是为什么在返回到请求的原始路径之前,您会看到短暂的闪光。您应该考虑定义自己的<代码> Link查询> /Cult>组件,它封装下一个链接组件,并将要保留的查询字符串追加到任何这样的链接。@ JAXX,这正是我最后采取的路线。它无论如何都不优雅,不幸的是需要一些修改,但这是迄今为止我发现的唯一有效的解决方案。谢谢@特克斯,我没有。我最终选择了完全不同的方向,因为这太难了。@Terkhos你能谈谈你是如何解决这个问题的吗?@invalidtoken我使用了第一条评论中描述的确切方法。用这个新组件替换我页面上的每一个链接并不优雅,但事实证明它花费的时间更少。