skip to Main Content

An Ionic React application is useless in a browser until this bug is fixed.

This issue is a problem in both versions of @ionic/react 7.4 and 7.5.

I have two simple routes defined as follows:

<IonRouterOutlet id="main">
...
<Route path="/campaigns" exact={true} render={props => <CampaignList {...props} />} />
<Route path="/campaign/:title" exact={true} render={props => <CampaignDetail {...props} />} />
...
</IonRouterOutlet>

The first route displays a list and each list item has an onClick method defined which calls a method titled getCampaignDetail which navigates to the second route as follows:

const getCampaignDetail = (title:string) => {
  navigate(`/campaign/${title}`, 'root');
}

When i load my app, it defaults to /campaigns

That view loads without issue and displays the list

If i tap a list item it correctly navigates to /campaign/:title

Then, i use the browser’s back button to load /campaigns

The /campaigns view loads without issue

Then, upon tapping a different list item i can say that i am absolutely positive that it attempts to load a different :title because:

  1. i am console logging the value before it navigates and seeing the value is clearly different
  2. The URL in the browser clearly is showing as though the parameter :title is different and has changed from the last time i visited this route

Despite this, when i console log the :title in the CampaignDetail component which is what loads at /campaign/:title inside it’s useIonViewDidEnter method, the :title is printing as though its value has not changed from the first time i visited /campaign:title

In my CampaignDetail component i have tried retrieving the parameter in one of 2 ways, first directly from props:

type MatchParams = {
  title: string;
};
const CampaignDetail: React.FC<RouteComponentProps> = (props) => {
const { title } = props.match.params as MatchParams;
...

And also with the useParams hook:

const CampaignDetail: React.FC<RouteComponentProps> = (props) => {
const { title } = useParams<{ title: string; }>();
...

and it is in the useIonViewDidEnter method, where i am attempting to console log :title

useIonViewDidEnter(() => {
  console.log("PARAMETER:", title);
});

This behavior only occurs after having used the browser’s back button.

Why is the parameter not reflecting the correct value for subsequent visits after having used the browser’s back button?

In an attempt to fix this after reading documentation and doing other research into this issue I have tried adding a key to the route as a solution as follows:

<Route path="/campaign/:title" exact={true} render={props => <CampaignDetail key={props.match.params.title} {...props} />} />

however, this results in EVEN WORSE BEHAVIOR in that after having used the browsers back button subsequent visits to /campaign:title cause the useIonViewDidEnter method to execute several times and with each execution i am seeing the :title act as if it is toggling between the two values i have visited with each print to the console. First i see the value as it was for the first time i visited, then the new value, then it prints the first value and so on about 3-4 times before it finally stops.

Seeing that behavior speaks volumes in that having used the browser’s back button clearly causes strange behavior with respect to route parameters.

What can i do to fix this?

UPDATE:

I am noticing that when i hit the browser’s back button while at the route /campaign/:title that the useIonViewDidEnter function in the component CampaignDetail is firing again when it should not given that i had left that route and navigated back to /campaigns.

OTHER ODD BEHAVIOR:

As per @Aafaq’s suggestion that i check location as a means of troubleshooting, i did this and have discovered strange behavior as a result.

If i comment out the useIonViewDidEnter method all together and use the following useEffect hook with location to check for path changes as follows:

  const campaignDetailTitleRef = useRef('');

  useEffect(() => {

    const parts = location.pathname.split('/');
    const getPathTitle = parts[2];

    if (getPathTitle && getPathTitle !== campaignDetailTitleRef.current) {
      campaignDetailTitleRef.current = getPathTitle;
      console.log("PARAMETER:", getPathTitle);
    }
  
  },[location.pathname]);

When the app loads which launches the route /campaigns and then i click on a list item, i see that console.log("PARAMETER:", getPathTitle); only prints once as expected when /campaign/:title loads and it is displaying the correct value as it was parsed from location.

Then i hit the browser’s back button, and subsequently, i click a different list item, and while the value of getPathTitle is actually printing correct now having retrieved that value from location instead of params, i am seeing console.log("PARAMETER:", getPathTitle); print twice which tells me that either campaignDetailTitleRef.current = getPathTitle is not getting set after the hook runs the first time or the component is loading twice, it is hard to tell which is the case. It is difficult to troubleshoot what is happening.

Something as simple as page navigation with just one dynamic parameter in the url should not be so difficult. This renders Ionic React worthless in a browser at this time.

2

Answers


  1. Chosen as BEST ANSWER

    It seems that wrapping routes with the <Switch> component makes sure that only one route is matched at a time and works to prevent the behavior i described.


  2. I will suggest you to use the useLocation hook from react-router-dom to log the current location and its state for debugging purposes. This can help you identify any unexpected behavior related to route changes. Example given below:

    import { useLocation } from 'react-router-dom';
    
    const CampaignDetail: React.FC<RouteComponentProps> = (props) => {
      const { title } = useParams<{ title: string }>();
      const location = useLocation();
    
      React.useEffect(() => {
        // ... Logs for debugging purpose
        console.log('Location:', location);
        console.log('Title:', title);
        // ... You can put rest of your logic here
      }, [location, title]);
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search