Url params are not updated using useHistory

Hi everyone!

I think I misunderstand how routing is working with Ionic/React.

Context

  • I want to create an app with a basic home page that redirect to some project pages.
  • Projects are saved in local storage and loaded at the app initialization.
  • A project page url is generated from its project data

Problem

When I open a project page the second time, the data is not refreshed (still the first opened project)

Working scenario

  • I open the project 1
  • the project 1 is displayed
  • I use the browser back button
  • I open the project 2
  • the project 2 is displayed

Not working scenario

  • I open the project 1
  • the project 1 is displayed
  • I use my custom back button (history.push("/"))
  • I open the project 2
  • the project 1 is displayed

My Code

I upload a minimal git repo here
This is how I do

App.tsx

const App: React.FC = () => (
  <IonApp>
    <IonReactRouter>
      <IonRouterOutlet>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/project/:projectName" component={Project} />
      </IonRouterOutlet>
    </IonReactRouter>
  </IonApp>
);

Home.tsx

const Home: React.FC = () => {
  const history = useHistory()

  // loaded from local storage, simplified for debugging purpose
  const projects: ProjectData[] = [<data>]

  function openProject(projectName: string) {
    console.debug("[home page]", "open a project:", projectName)

    // do something...

    const projectUrl = `/project/${projectName}`
    console.debug("[home page]", "project url:", projectUrl)
    history.push(projectUrl)
  }

  return (
    <IonPage>
      <IonContent fullscreen className={"homePage"}>
        
        <header>
          <h1>
            {`${projects.length} projet${projects.length > 1 ? 's' : ''}`} 
          </h1>  
        </header>
        
        <div className={"grid"}>
          {projects.map((project) =>
            <div className={"project"} key={project.id} onClick={() => openProject(project.name)}>
              {project.name}
            </div>
          )}
        </div>
      
      </IonContent>
    </IonPage>
  );
};

Project.tsx

const Project: React.FC<ProjectProps> = ({ match }) => {
  const history = useHistory()

  const [projectName, setProjectName] = useState<string|undefined>(undefined)

  useIonViewWillEnter(() => {
    console.debug("[project page]", "match params:", match)
    const _projectName = match.params.projectName;
    console.debug("[project page]", "project name:", _projectName)
    setProjectName(_projectName)
  })

  useEffect(() => {
    if (projectName === undefined) return;
    console.debug("[project page]", "useEffect, projectName:", projectName)

    // do something...

  }, [projectName])

  function goBackToHome() {
    console.debug("[project page]", "go back to home page")

    // do something...

    history.push("/")
  }

  return (
    <IonPage className={"projectPage"}>
      <IonContent fullscreen>
        {projectName !== undefined && (
          <>
            <header>
              <button className={"returnButton"} onClick={goBackToHome}>
                {"<"}
              </button>
              <h1>
                {projectName}
              </h1>  
            </header>
          </>
        )}
      </IonContent>
    </IonPage>
  );
};

Can someone explain me why the RouteComponentProps are not updated and how to make it working?
Or maybe my app design is wrong?

3 Likes

Hi,

I am facing a very similar issue. Though at first I use routerLink and then history.push to navigate further and back to the list (‘tasks’).

    <IonItem 
      detail={task.id > 0} 
      disabled={task.date !== currentDateFormatted}
      routerDirection='forward'
      routerLink={`/task-type/${task.id}`}
      onClick={() => {
        console.debug(`/task-type/${task.id}`);
      }}
    >

After going into one task, the last step that I do is history.push(’/tasks’). All the list items are generated correctly. Yet when I click on any item, it uses the previous task.id while in the click event console says that task.id is the one I actually clicked.

Surely there is no difference in navigating with routerLink and history? Also I can’t comprehend why, within the inspector, the web page address never changes when using history.push…?

So how to pinpoint the issue? :point_up_2: I take it that either Ionic React Router or React Router doesn’t send the new params as the component already exists and the is rendered with old info?

<Route path="/task-type/:taskId?" component={ChooseTaskType}></Route>

For m that’s exactly the clue. I use history.replace(pathname, State) and in the view I get useHistory() but I need to pull to refresh the good info with <IonRefresher>.

I am facing the same issue as @antoinebassin and @yanisl described.

I also have the problem when I use the TabButton to navigate back to my “Home” page.

I think this is a caching problem of Ionic, because Ionic caches the pages so that it is easier to navigate back, but somehow there is no way to manually clear this cache. This would be useful in the case where you use history.push("/").

Maybe there is a method for that, but I did not find anything.

1 Like