Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: (WIP) basic expo-router implementation #20

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gorbypark
Copy link

@gorbypark gorbypark commented Oct 8, 2024

This is a work in progress, do not merge. Just adding here to get some feedback.

I have a basic implementation of expo-router support. Originally I was playing around with just wrapping TabView as I posted on X, but parbez pointed me in the direction of this https://github.com/EvanBacon/expo-router-layouts-example which is a much better solution.

However withLayoutContext isn't well documented, it's taking four generic params however all the examples from the expo-router-layouts-example repo only have two! I believe I have the types of withLayoutContext figured out, however it seems the types of react-native-bottom-tabs/react-navigation are kinda messed up at the moment. I'm not 100% it isn't just me, however the exported types don't seem to work.

Anyways, in order to bypass the left-hook check to push to this branch, I am importing NativeBottomTabNavigationOptions from where it should be imported from, but it's not working. If you uncomment the line // import { BottomTabNavigationOptions } from '@react-navigation/bottom-tabs'; and use that as the first argument of withLayoutContext, all the typing works perfectly (assuming that bottom-tabs and react-navigation-bottom-tabs have the exact same api).

I am opening this PR for comments on the type issue I'm facing along with the structure of where this should be located in the project. I stuck it in src/expo-router for now. Also, it might be worth thinking about how or if we should integrate expo/expo-router into the example app / create another app in the monorepo for expo?

I'm also going to just dump the code here for easier testing. If you have an expo-router based project, just copy this somewhere into your project and then in a _layout.tsx just import it and use it like you would Tabs, Stack or Slot.

import { withLayoutContext } from 'expo-router';

import {
  createNativeBottomTabNavigator,
  NativeBottomTabNavigationEventMap,
  NativeBottomTabNavigationOptions,
} from 'react-native-bottom-tabs/react-navigation';

// This should be imported from react-native-bottom-tabs/react-navigation which is
// exporting NativeBottomTabNavigationOptions but the types seem to be broken at
// at the moment..
import { BottomTabNavigationOptions } from '@react-navigation/bottom-tabs';

import type {
  ParamListBase,
  TabNavigationState,
} from '@react-navigation/native';

const { Navigator } = createNativeBottomTabNavigator();

export const NativeTabs = withLayoutContext<
  BottomTabNavigationOptions,
  typeof Navigator,
  TabNavigationState<ParamListBase>,
  NativeBottomTabNavigationEventMap
>(Navigator);

example _layout.tsx

import { NativeTabs } from "@/components/TabNavigator";

export default function Index() {
  return (
    <NativeTabs>
      <NativeTabs.Screen name="index" options={{ title: "Yolo" }} />
      <NativeTabs.Screen name="new" options={{ title: "OOOH, SHINY" }} />
    </NativeTabs>
  );
}

@gorbypark gorbypark marked this pull request as draft October 8, 2024 14:23
@okwasniewski
Copy link
Collaborator

Hey, thanks for working on this @EvanBacon created this repo https://github.com/EvanBacon/expo-router-react-native-bottom-tabs showcasing how to use it with Expo Router.

I think this should be added to the docs, in the Expo router section and no changes should be required on the library side:

import { withLayoutContext } from "expo-router";
import { createNativeBottomTabNavigator } from "react-native-bottom-tabs/react-navigation";

export const Tabs = withLayoutContext(
  createNativeBottomTabNavigator().Navigator
);

@gorbypark
Copy link
Author

gorbypark commented Oct 8, 2024

Hey, thanks for working on this @EvanBacon created this repo https://github.com/EvanBacon/expo-router-react-native-bottom-tabs showcasing how to use it with Expo Router.

I think this should be added to the docs, in the Expo router section and no changes should be required on the library side:

import { withLayoutContext } from "expo-router";
import { createNativeBottomTabNavigator } from "react-native-bottom-tabs/react-navigation";

export const Tabs = withLayoutContext(
  createNativeBottomTabNavigator().Navigator
);

Yeah that's a good option to just document it, that snippet is pretty clear and concise.. However, I'm still having issues with the types, I'm getting Could not find a declaration file for module 'react-native-bottom-tabs/react-navigation'. '/Users/mhamilton/Documents/code/cobbler/node_modules/react-native-bottom-tabs/lib/commonjs/react-navigation/index.js' implicitly has an 'any' type.ts(7016)
on the import of createNativeBottomTabNavigator, and thus the Tabs and Tabs.Screen component props aren't typed when using it. I suppose that's another issue, but just wondering if it's maybe just me somehow having issues with the types?

Besides the odd import paths, this seems to be working to type all the props (options, screenOptions, etc)

import { withLayoutContext } from "expo-router";

import { createNativeBottomTabNavigator } from "react-native-bottom-tabs/lib/typescript/commonjs/src/react-navigation";

import type {
  NativeBottomTabNavigationEventMap,
  NativeBottomTabNavigationOptions,
} from "react-native-bottom-tabs/lib/typescript/commonjs/src/react-navigation";

import type {
  ParamListBase,
  TabNavigationState,
} from "@react-navigation/native";

export const NativeTabs = withLayoutContext<
  NativeBottomTabNavigationOptions,
  ReturnType<typeof createNativeBottomTabNavigator>["Navigator"],
  TabNavigationState<ParamListBase>,
  NativeBottomTabNavigationEventMap
>(createNativeBottomTabNavigator().Navigator);

@okwasniewski
Copy link
Collaborator

Looks like there is an issue with types in general. I'm going to look into this tomorrow

@CodeWithShreyans
Copy link

What if expo-router is made an optional dep? A simple Tabs export could be good for UX.

@okwasniewski
Copy link
Collaborator

What if expo-router is made an optional dep? A simple Tabs export could be good for UX.

In the long run it should be the other way around, where Expo Router adds this small export from their package as they do for every navigator.

I will create a docs page soon so this will be better documented.

@okwasniewski
Copy link
Collaborator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants