feat(IonReactHashRouter): migrate to a functional component and react router 6

Co-authored-by: Sean Perkins <13732623+sean-perkins@users.noreply.github.com>
This commit is contained in:
Maria Hutt
2025-06-12 16:14:24 -07:00
parent 205a7056d7
commit 7ff8994d12

View File

@ -1,53 +1,46 @@
import type { Action as HistoryAction, History, Location as HistoryLocation } from 'history'; import type { Action as HistoryAction, Location as HistoryLocation } from 'history';
import { createHashHistory as createHistory } from 'history'; import type { PropsWithChildren } from 'react';
import React from 'react'; import React, { useEffect, useRef } from 'react';
import type { BrowserRouterProps } from 'react-router-dom'; import type { HashRouterProps } from 'react-router-dom';
import { Router } from 'react-router-dom'; import { HashRouter, useLocation, useNavigationType } from 'react-router-dom';
import { IonRouter } from './IonRouter'; import { IonRouter } from './IonRouter';
interface IonReactHashRouterProps extends BrowserRouterProps { export const IonReactHashRouter = ({ children }: PropsWithChildren<HashRouterProps>) => {
history?: History; const location = useLocation();
} const navigationType = useNavigationType();
export class IonReactHashRouter extends React.Component<IonReactHashRouterProps> { const historyListenHandler = useRef<(location: HistoryLocation, action: HistoryAction) => void>();
history: History;
historyListenHandler?: (location: HistoryLocation, action: HistoryAction) => void;
constructor(props: IonReactHashRouterProps) { const registerHistoryListener = (cb: (location: HistoryLocation, action: HistoryAction) => void) => {
super(props); historyListenHandler.current = cb;
const { history, ...rest } = props; };
this.history = history || createHistory(rest);
this.history.listen(this.handleHistoryChange.bind(this));
this.registerHistoryListener = this.registerHistoryListener.bind(this);
}
/** /**
* history@4.x passes separate location and action * Processes navigation changes within the application.
* params. history@5.x passes location and action *
* together as a single object. * Its purpose is to relay the current `location` and the associated
* TODO: If support for React Router <=5 is dropped * `action` ('PUSH', 'POP', or 'REPLACE') to any registered listeners,
* this logic is no longer needed. We can just assume * primarily for `IonRouter` to manage Ionic-specific UI updates and
* a single object with both location and action. * navigation stack behavior.
*
* @param location The current browser history location object.
* @param action The type of navigation action ('PUSH', 'POP', or
* 'REPLACE').
*/ */
handleHistoryChange(location: HistoryLocation, action: HistoryAction) { const handleHistoryChange = (location: HistoryLocation, action: HistoryAction) => {
const locationValue = (location as any).location || location; if (historyListenHandler.current) {
const actionValue = (location as any).action || action; historyListenHandler.current(location, action);
if (this.historyListenHandler) {
this.historyListenHandler(locationValue, actionValue);
} }
} };
registerHistoryListener(cb: (location: HistoryLocation, action: HistoryAction) => void) { useEffect(() => {
this.historyListenHandler = cb; handleHistoryChange(location, navigationType);
} }, [location, navigationType]);
render() { return (
const { children, ...props } = this.props; <HashRouter>
return ( <IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>
<Router history={this.history} {...props}> </HashRouter>
<IonRouter registerHistoryListener={this.registerHistoryListener}>{children}</IonRouter> );
</Router> };
);
}
}