DEV Community

Pedro Palhari for teepad

Posted on

Creating a stack navigator, with proper animations, using Ionic and React.

So, I've been really diggin' the Ionic and React integration. I usually add it to an already existing React application and go from there.

But, recently, I've stumbled upon something. I want to control the direction of my transitions between pages.

And the docs, they sure do provide something to work with. You can pass a prop called routeDirection to some specific Ionic components. But you can't control it with code.

But, I, want to control the direction of my transitions, with my own code, so I started looking into it.

It happens that these transitions are actually part of a Context called NavContext inside @ionic/react, so you can just:

import { useContext } from "react";
import { NavContext } from "@ionic/react";


function MyComponent(){
  let navigationContext = useContext(NavContext);

  //forbidden by the gods, a back-animated-push
  navigationContext.navigate("/route", "back"); 
}

So, to create a stack animator, all you need is a hook to handle the screens you've passed, and one singleton array shared between them:

//IonicCustomNavigation.ts

import { useContext } from "react";
import { NavContext } from "@ionic/react";

//Hook to encapsulate navigation context
export function useContextNavigation() {
  let navigation = useContext(NavContext);

  return navigation;
}

//Stack
let stack: string[] = ["/"];
export function useStackNavigation() {
  let navigation = useContextNavigation();

  console.log(stack);

  function navigateTo(screen: string) {
    let indexOfScreenOnStack = stack.indexOf(screen);
    if (indexOfScreenOnStack != -1) {
      if (indexOfScreenOnStack == stack.length - 1) return;

      stack = stack.slice(0, indexOfScreenOnStack);
      navigation.navigate(screen, "back");
    } else {
      navigation.navigate(screen, "forward");
    }
    stack.push(screen);
  }

  return navigateTo;
}

And done! You'd need to pass extra parameters to the navigateTo function if you want to handle state, but that is simple enough.

Alt Text

I spent some time working around a solution, and that seems to do it.

For reference, the versions I'm using of Ionic and Ionic/React are:

/**
"@ionic/react-router@^5.0.0":
  version "5.0.0"
  resolved "https://registry.yarnpkg.com/@ionic/react-router/-/react-router-5.0.0.tgz#939e9619cceebc2603cc738eb276d3bd6b523762"
  integrity sha512-IjBSZtel1W9zJvdwI9Z8LOHS9eOWhulumiTuvG2yD1Qj6dQ8Cp67zOYdHhxkhH2JBnxILC+vJgXp/0pnEFIu2Q==
  dependencies:
    tslib "*"

"@ionic/react@^5.0.0":
  version "5.0.0"
  resolved "https://registry.yarnpkg.com/@ionic/react/-/react-5.0.0.tgz#12a7ea61ce7e9e35a27768628370020bbfd6091a"
  integrity sha512-Q6uPAyWa01XLoZ7MdeM0xRKID8SR/hFuoGIjXFlawq2TKwiPCZbSjegHXdFHcX0LHTC/iQuu4Ly2d8UaD5ljZQ==
  dependencies:
    "@ionic/core" "5.0.0"
    ionicons "^5.0.0"
    tslib "*"
*/

Top comments (0)