nandorojo / expo-gatsby-navigation

🤵Make Gatsby and React Navigation play nicely together with an Expo/React Native Web app.
12 stars 0 forks source link

TypeScript error in navigate func props #5

Open augsteyer opened 3 years ago

augsteyer commented 3 years ago

Hey, wanted to first thank you for the awesome work on this. It's simple, but very much needed addition to my Gatsby/Native home project. Quite a novice in JS & TS, so not quite sure how to get around this. Just spotting a TS error when trying to use one of your hooks:

import { useRouting } from 'expo-gatsby-navigation'

export default function App(): JSX.Element {
    const { navigate } = useRouting()

    return (
        <View>
            ...
            <Button title={'Go to User2'} onPress={() => navigate({ routeName: 'User', web: {
                to: '/user/other'
                } })} />
        </View>
    )
}
...

The "soft" TS error is around the usage of "to" inside web. When I click on the useRouting definition I find this in the expo-nav-core module: node_modules/expo-navigation-core/build/hooks/use-routing/index.d.ts:

export default function useRouting<T extends RouteProp<ParamListBase, string>,...
   navigate: <To extends {
        routeName: string;
        key?: string | undefined;
        params?: object | undefined;
        web?: {
            path?: string | undefined;
            as?: string | undefined;
        } | undefined;

I am assuming it's because it uses the native useRouting definition instead of the gatsby one, but how does one specify (extend?) which type definition to use?

nandorojo commented 3 years ago

You're probably right that it's using the native one. I mostly use expo-next-react-navigation, and made this for people who want it for Gatsby, so I missed that one.

We could the export type of the web file for useRouting, maybe call it UseGatsbyRouting. Then in the main index.ts file, export useRouting and cast it export { useRouting: useRouting as UseGatsbyRouting }.

I'd accept a PR on this if you want to try that. Be sure to work on the v5 branch.

augsteyer commented 3 years ago

I tried for a while, but my lack of understanding how TS works is showing at this point ^_^ So I am cheating at this point by doing this:

() => navigate<NavigateRewrite>({
                routeName: 'User', web: {
                    to: '/user/'
                }

NavigateRewrite being:

import { NavigateTo, WebRoute } from 'expo-gatsby-navigation/build/hooks/use-routing/types'

export type NavigateRewrite = NavigateTo & WebRoute<string, string>

I am sure it's dirty, but as I said. I have no clue what I am doing. Just picked up React Native, Gatsby & TS a week ago.

augsteyer commented 3 years ago

After a bit of digging today. I found that this module is possibly no longer needed. The @react-navigation/native itself provides the navigation configuration that allows proper web linking via the NavigationContainer config. It looks something like this.

const linking:LinkingOptions = {
        config: {
            initialRouteName: 'Home',
            screens: {
                Home: '/',
                User: {
                    path: 'user',
                    screens:{
                        User: '/',
                        Other: 'other'
                    }
                }
            },
        },
    }
...
<NavigationContainer linking={linking}>
    <RootStack.Navigator>
         <RootStack.Screen name="Home" component={HomeScreen}> .... </>
         <RootStack.Screen name="User" component={UserScreen}>
               <UserStack.Navigator>
                     <User.Screen name={'User'} component={UserComponent} />
                     <User.Screen name={'Other'} component={OtherScreen} />
               </>
         </>

Tried both the { navigation } prop and the Link they provide:

<Button title={'Other (via Navigate)'} onPress={() => navigation.navigate('Other')} />
<Link to={'/user/other'}>Other (via Link)</Link>

Producing web links in regular Expo Web and Gatsby looking like this: http://localhost:8000/user & http://localhost:8000/user/other. A small win for Native & Web being friends in the future.

nandorojo commented 3 years ago

You miss out on Gatsby Link’s benefits though, like prefetching.

augsteyer commented 3 years ago

Aw man, forgot about that. Back to the drawing board!

nandorojo commented 3 years ago

Is your main concern the typescript suggestions?

augsteyer commented 3 years ago

I wish. Every time I add a module that promised Native + Web compatibility things just start falling apart at the seems. Whether Gatsby complaining or just Web or Native. I then find "workarounds" online to fix one part, but the workaround itself creates another issue in another place. So I feel like reducing the complexity of the stack would make my beginner life a bit easier at this point.

nandorojo commented 3 years ago

Yeah that makes sense. For what it’s worth, just expo web isn’t bad.

If I were to suggest a beginner stack, I’d maybe say expo web + React navigation. Keep it simple.

Personally, I’m a much bigger fan than Next.js over Gatsby, having used both quite a lot. I also have a library for expo + next.js navigation, which I use in my actual production apps. Most problems with Expo + Next you find, you’ll probably see an issue on Github made by me that I eventually figured out.

Another thing I built is a styling library that’s compatible with Expo + Next: https://github.com/nandorojo/dripsy

I will say, I’m convinced expo and nextjs is the best possible stack there is. Development time for both is super quick. Next websites are seriously fast. But if you just want to start with an expo web site, that’s totally fine too. I’ve launched a SAAS product into production that way and it worked well.

nandorojo commented 3 years ago

The issues you’re facing with universal packages are often related to the fact that Gatsby also server side renders. Normal expo web probably won’t face those issues, since it only loads on the client.

augsteyer commented 3 years ago

Nice, I might take a look at dropping Gatsby. Will see if I have less friction with Next. My biggest concern is that I am trying to build an App, building at the same time for Web was supposed to speed up the process, not slow it down. That's what I get for trying to learn a new language (JS) and use all kinds of new stacks at the same time. I'll just try out Next with your packages, then go just Expo if that is too much. Thanks for the advice.

nandorojo commented 3 years ago

Makes sense. I think Gatsby isn’t a great use case for apps in general. Better for static sites like blogs, ecommerce, etc.

Not sure what you’re using for your database and stuff, but Firestore / Firebase auth is really good for React, especially when you’re just starting (https://github.com/nandorojo/swr-firestore).

augsteyer commented 3 years ago

I was going to be trying out Strapi as a separate data holder. I also needed some kind of "backend" screen for my yoga teachers to add classes and events. So that looked like a simple thing to use. I don't have to bother about building out my own admin panel, then building out an API for the data layer. The App/Web will just query the data via Graphql. At least that's the plan ^_^ I am coming from the PHP world, so having a monolith gigantic app is something I am used to. Heck, WordPress was going to be my data layer / admin panel at first. But the more I read about JAMStacks, the deeper I got into this mess...

nandorojo commented 3 years ago

Ha gotcha, I like to keep it simple. Fetch data in a React hook, display it with stateful UI, and you’re done. Graphql would work well for that.