Teardown

Type-Safe Navigation

Navigate with full TypeScript type checking.

@teardown/navigation provides type-safe hooks that ensure your navigation calls are valid at compile time.

useTypedNavigation

Get a typed navigation object for navigating between screens:

import { useTypedNavigation } from "@teardown/navigation";

function MyComponent() {
  const navigation = useTypedNavigation();

  const handlePress = () => {
    // Fully type-checked - TypeScript knows the route exists
    navigation.navigate("/users/:userId", { userId: "123" });
  };

  return <Button onPress={handlePress} title="View User" />;
}

useTypedParams

Access route parameters with type safety:

import { useTypedParams } from "@teardown/navigation";

// In src/_routes/users/[userId].tsx
function UserProfileScreen() {
  // TypeScript knows userId is a string
  const { userId } = useTypedParams<"/users/:userId">();

  return <Text>User ID: {userId}</Text>;
}

useTypedRoute

Get the full route object including params:

import { useTypedRoute } from "@teardown/navigation";

function UserScreen() {
  const route = useTypedRoute<"/users/:userId">();

  // Access route name and params
  console.log(route.name);   // "users/[userId]"
  console.log(route.params); // { userId: string }

  return <Text>User: {route.params.userId}</Text>;
}

The useTypedNavigation hook returns these methods:

Navigate to a screen. If the screen is already in the stack, it navigates back to it:

const navigation = useTypedNavigation();

// Route without params
navigation.navigate("/settings");

// Route with required params
navigation.navigate("/users/:userId", { userId: "abc" });

// Route with optional params
navigation.navigate("/search/:query?", { query: "react" });
navigation.navigate("/search/:query?"); // query is optional

push

Push a new screen onto the stack (only in stack navigators):

// Always adds a new screen, even if same route
navigation.push("/users/:userId", { userId: "123" });
navigation.push("/users/:userId", { userId: "456" });
// Stack now has two user screens

replace

Replace the current screen without adding to history:

// Replace current screen
navigation.replace("/dashboard");

goBack

Go back to the previous screen:

navigation.goBack();

canGoBack

Check if going back is possible:

if (navigation.canGoBack()) {
  navigation.goBack();
} else {
  navigation.navigate("/");
}

reset

Reset the navigation state entirely:

navigation.reset({
  index: 0,
  routes: [{ name: "index" }],
});

setParams

Update the current screen's params:

navigation.setParams({ userId: "newId" });

Type Safety in Action

Compile-Time Errors

TypeScript catches navigation errors before runtime:

// Error: Route "/nonexistent" does not exist
navigation.navigate("/nonexistent");

// Error: Missing required param "userId"
navigation.navigate("/users/:userId");

// Error: Unknown param "invalid"
navigation.navigate("/users/:userId", { userId: "1", invalid: true });

Autocomplete

Your editor provides autocomplete for:

  • Available route paths
  • Required and optional parameters
  • Parameter types

Dynamic Routes with Params

Required Parameters

// File: src/_routes/posts/[postId].tsx
// Route: /posts/:postId

// Navigating
navigation.navigate("/posts/:postId", { postId: "42" });

// Accessing params
const { postId } = useTypedParams<"/posts/:postId">();
// postId: string

Optional Parameters

// File: src/_routes/search/[[query]].tsx
// Route: /search/:query?

// Both valid
navigation.navigate("/search/:query?");
navigation.navigate("/search/:query?", { query: "react native" });

// Accessing params
const { query } = useTypedParams<"/search/:query?">();
// query: string | undefined

Catch-All Parameters

// File: src/_routes/docs/[...path].tsx
// Route: /docs/*

navigation.navigate("/docs/*", { path: ["api", "navigation"] });

// Accessing params
const { path } = useTypedParams<"/docs/*">();
// path: string[]

Parameter Validation

Use createParamSchema for runtime validation with Zod:

import { defineScreen, createParamSchema } from "@teardown/navigation";
import { z } from "zod";

const params = createParamSchema({
  userId: z.string().uuid(),
  tab: z.enum(["profile", "settings"]).optional(),
});

function UserScreen() {
  // Params are validated and typed
  const { userId, tab } = useTypedParams<"/users/:userId">();
  
  return <Text>User: {userId}, Tab: {tab ?? "profile"}</Text>;
}

export default defineScreen({
  component: UserScreen,
  params,
});

URL Building

Use buildUrl to construct URLs programmatically:

import { buildUrl } from "@teardown/navigation";

// Returns "/users/123"
const url = buildUrl("/users/:userId", { userId: "123" });

// With query params
const searchUrl = buildUrl("/search/:query?", { query: "react" });

Next Steps