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?

2 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>