Ionic-framework: Passing custom browser history into IonReactRouter

Created on 25 Jan 2020  路  12Comments  路  Source: ionic-team/ionic-framework

Ionic version:


[x] 4.x
[ ] 5.x

I'm submitting a ...

[ ] bug report
[x] feature request

Current behavior:
IonReactRouter doesn't give you the option to pass in a custom browser history. It would be great if you could do so like you can if you use the Router component from react-router-dom (https://reacttraining.com/react-router/web/api/Router)

Expected behavior:
To be able to use custom history like so

// history.ts
import { createBrowserHistory } from 'history';

const history = createBrowserHistory();

export default history;

// App.tsx
import { IonReactRouter } from '@ionic/react-router';
import history from './history';

const App: FC = () => (
  <IonReactRouter history={history}>
    {...}
  </IonReactRouter>
)
react triage

Most helpful comment

IonReactRouter currently wraps BrowserRouter, which doesn't accept pre-built history.

I'll look into changing it to wrap Router instead and provide the browser stuff ourselfs.

All 12 comments

I agree with you, and I am interested in a solution for that. FYI, I had recently put a bounty on an old question on Stackoverflow that you might wanna check https://stackoverflow.com/questions/55884643/ionic-4-routing-with-angular-6

Basically the situation, as I understand it, is the following:

  1. There was a way to set browser history (or at least, navigation history) in Ionic

  2. There is not anymore

  3. An Angular (or React) solution is not enough to solve the problem

Another concrete use case: user needs to listen for the appUrlOpen to intercept a Universal Link, and navigate to that component, e.g. :

# history.ts
import { createBrowserHistory } from 'history';
import { History } from 'history';

export type ReadonlyBrowserHistory = Readonly<History>
export const browserHistory: ReadonlyBrowserHistory = createBrowserHistory();
# App.tsx
import { browserHistory } from './history';
...
     <IonApp>
        <IonReactRouter history={browserHistory}>
          <IonRouterOutlet id='main' key={String(user)}>
            <Route path='/' render={() => user === null ? <LoggedOutRouter /> : <LoggedInRouter />} />
          </IonRouterOutlet>
        </IonReactRouter>
        <Menu />
      </IonApp>
# File listening for Universal Link events
import {browserHistory} from './history'

IonicApp.addListener("appUrlOpen",` (data) => {
  browserHistory.push(data.url)
}

To my knowledge there's not a clean way to handle this.

IonReactRouter currently wraps BrowserRouter, which doesn't accept pre-built history.

I'll look into changing it to wrap Router instead and provide the browser stuff ourselfs.

When we can apply a custom browser history to the IonReactRouter component?

In case anyone finds this issue and is disappointed this hasn't been implemented yet, here's a quick workaround which seems to work for us.

import React from 'react'
import { History } from 'history'
import { useHistory } from 'react-router'

// Add custom property 'appHistory' to the global window object
declare global {
  interface Window { appHistory: History }
}

const MyApp: React.FC = () => {
  // Store the history object globally so we can access it outside of React components
  window.appHistory = useHistory()

  ...
}

You are now able to access and mutate the history from anywhere in your app using the window.appHistory property.

Hi @elylucas, are there any updates on this?

Another workaround that seems to be working for us (at least from initial testing):

import { useHistory } from "react-router-dom";

const SomeFunctionalComponent: React.FC = () => {
  let history = useHistory();
  history.push('/someRoute')
}

Hi @mogusbi and all,

There is a dev build available where you can pass in a custom history to IonReactRouter. You can give it a try by installing:

npm i @ionic/[email protected] @ionic/[email protected]

And to pass the history object:

import { createBrowserHistory } from 'history';
const history = createBrowserHistory();

<IonReactRouter history={history}>

Let me know how it works for you. If all is good this will be available in the next release.

Thanks

Hi @elylucas, this appears to be working well so far! Thank you for putting this together!

I'm going to spend a bit more time testing it but so far so good

@elylucas @mogusbi Unfortunately, it doesn't work.

If I create and pass a history object and then use it to navigate, then an empty page appears.
The useHistory react hook also does not work.
Here is an example: https://codesandbox.io/s/bug-ionreactrouter-with-history-c6u1p?file=/src/App.tsx:1018-1086

@elylucas @mogusbi I found the problem. I installed the wrong version (v5.x.x) of the history package. For the react router v5.x.x should be used the history v4.x.x
Sorry for that. It works perfect!

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

giammaleoni picture giammaleoni  路  3Comments

SebastianGiro picture SebastianGiro  路  3Comments

gio82 picture gio82  路  3Comments

Nick-The-Uncharted picture Nick-The-Uncharted  路  3Comments

Macstyg picture Macstyg  路  3Comments