You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重写React-Router-Dom v5的History.push方法自动添加哈希参数?

在React Router v5中直接重写history.push自动附加哈希查询参数

问题描述

我希望调用history.push导航时,自动把查询字符串的哈希值附加到URL里。目前我写了一个自定义hook返回增强版的pusher函数,但需要在多处替换history.push为这个自定义函数,请问能不能直接重写history.push方法?我用的是react-router-dom v5版本。

现有代码:

let pusher: null | ((a: unknown, b?: unknown) => void) = null;

/**
 * This hook will push a hashed value of query string of the url
 * 
 * Don't mind about memory leak, it's `Singletom`
 * @param history an instance of History from useHistory
 * @returns `Pusher` an enhance version of `History.push`
 */
export default function useHashPusher(history: ReturnType<typeof useHistory>){

    const sha256 = useSha256();

    if(!pusher) {
        pusher = function(...args) {
            const data = args[0];
            if(typeof data === 'object' && data && 'search' in data){
                const raw = data['search' as keyof typeof data];
                if(raw){
                    const hashed = sha256.hash(raw);
                    (data['search' as keyof typeof data] as string) = `${raw}&hash=${hashed}`;
                    console.log(data);
                }
            }
            console.log('overrided!', args[0]);
            history.push(...args);
        };
    }
    
    return pusher;
}

解决方案

当然可以直接重写history.push方法,只需在hook中保存原始push方法,用自定义逻辑包装后替换原方法即可,这样全局调用history.push都会自动应用哈希附加逻辑,无需逐一替换。

实现代码

import { useHistory } from 'react-router-dom';
import useSha256 from './your-sha256-hook-path'; // 替换为你的useSha256实际路径

export default function useOverrideHistoryPush() {
    const history = useHistory();
    const sha256 = useSha256();

    // 仅执行一次重写,避免重复包装
    const originalPush = history.push;
    if (history.push !== originalPush) return;

    history.push = function(...args) {
        const [data, state] = args;
        let modifiedData = data;

        // 处理对象形式的路径参数
        if (typeof data === 'object' && data && 'search' in data) {
            const rawSearch = data.search as string;
            if (rawSearch) {
                const hashed = sha256.hash(rawSearch);
                // 创建新对象而非修改原对象,避免副作用
                modifiedData = {
                    ...data,
                    search: `${rawSearch}&hash=${hashed}`
                };
            }
        } 
        // 处理字符串形式的路径参数(如'/page?foo=bar')
        else if (typeof data === 'string') {
            const [pathname, search] = data.split('?');
            if (search) {
                const hashed = sha256.hash(search);
                modifiedData = `${pathname}?${search}&hash=${hashed}`;
            }
        }

        // 调用原始push方法,保持原有行为
        return originalPush.call(history, modifiedData, state);
    };

    // 可选:组件卸载时恢复原始push方法,避免影响其他组件场景
    // useEffect(() => {
    //     return () => {
    //         history.push = originalPush;
    //     };
    // }, [history, originalPush]);
}

使用方法

在应用根组件(如App.tsx)中调用该hook,全局生效:

import useOverrideHistoryPush from './useOverrideHistoryPush';

function App() {
    useOverrideHistoryPush();

    return (
        {/* 你的路由结构 */}
    );
}

注意要点

  • 新增了字符串形式路径的处理逻辑,覆盖history.push的所有调用场景,比原有代码更全面。
  • 采用创建新对象的方式修改参数,避免直接修改传入对象带来的意外副作用。
  • 若需在组件卸载后恢复原始push方法,可取消注释代码中的useEffect部分;如果是全局唯一调用,也可忽略该处理。

内容的提问来源于stack exchange,提问作者Hao.Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:33:25