Namby Pamby Magicians

    expo-gatsby-navigation
    TypeScript icon, indicating that this package has built-in type declarations

    0.0.8 • Public • Published

    Expo + Gatsby + React Navigation 🤵

    ** Not ready yet, coming soon :) **

    A set of hooks that wrap the react-navigation API that you're used to, and make it work with Gatsby's built-in routing.

    This library helps me use the Expo + Gatsby integration without stressing about navigation.


    Want to use next.js with expo instead? Check out expo-next-react-navigation.


    Example

    👾 Github Repo | 💻 Website | 📱 Open expo app directly | ☎️ Expo app website

    Install

    yarn add expo-gatsby-navigation

    Table of contents

    Set up

    Install gatsby with expo:

    • Install expo: npm install -g expo-cli

    • Init: expo init woohoo

    • cd woohoo

    • Install gatsby: yarn add gatsby gatsby-plugin-react-native-web

    • Create a gatsby-config.js and use the plugin - touch gatsby-config.js

    gatsby-config.js

    module.exports = {
        plugins: [
            `gatsby-plugin-react-native-web`,
            /* ... */
        ],
    }
    • Add /.cache and /public to your .gitignore file

    All done! Run yarn gatsby develop & open http://localhost:8000 👻

    I recommend becoming familiar gatsby's architecture with expo. Follow the docs on the Expo docs or see this article by Evan Bacon if you're curious.

    Usage

    Replace the following instances in your code after installation and setup:

    useNavigation 👉 useRouting

    -import { useNavigation } from 'react-navigation-hooks'
    +import { useRouting } from 'expo-gatsby-navigation'

    useLayoutEffect

    -import { useLayoutEffect } from 'react-navigation-hooks'
    +import { useLayoutEffect } from 'expo-gatsby-navigation'

    <TouchableOpacity /> 👉 <Link />

    -import { TouchableOpacity } from 'react-native'
    +import { Link } from 'expo-gatsby-navigation'
     
    -<TouchableOpacity onPress={() => navigate({ routeName: 'chat' })}>
    -  <Text>Go</Text>
    - </TouchableOpacity>
    +<Link routeName="chat" params={{ roomId: 'hey!' }}>
    +  Go
    +</Link>

    All set ⚡️

    API

    useRouting

    React hook that wraps useNavigation (from react-navigation) hook and makes it play nicely with Gatsby's built-in routing.

    It follows the same API as useNavigation.

    import { useRouting } from 'expo-gatsby-navigation`
     
    export default function Screen({ location }) {
      const { navigation, push, getParam, goBack } = useRouting()
     
      return <CoolComponent />
    }

    navigate

    Only argument is a dictionary with these values. Unlike react-navigation, this doesn't currently support a string as argument.

    • routeName: string, required
    • params: optional dictionary
    • web: Optional dictionary with added values for web, following the API from gatsby's navigate function.
      • to: (optional string) Fulfills the same value as to from gatsby Link component, overriding the routeName field. If you set this to /cars, it will navigate to /cars instead of the /routeName field. As a result, it will load the file located at src/pages/cars.js as the screen.
      • replace: (optional boolean) If true, replaces the current URL in history.

    Example: Navigate to a user

    export default function Home() {
        const { navigate } = useRouting()
     
        // goes to yourdomain.com/user
        // and sends the param to the screen component
        // see getParam() docs for more
        const onPress = () =>
            navigate({
                routeName: 'user',
                params: { id: 'chris' },
            })
     
        // 👇or this👇
        // goes to `yourdomain.com/profile`
        const navigateCleanLink = () =>
            navigate({
                routeName: 'user',
                params: { id: 'chris' },
                web: { to: `/profile` },
            })
     
        // 👇or this👇
        // 'profile' path overrides 'user' on web, so it uses the src/pages/profile.js file
        // even though it navigates to yourdomain.com/profile
        // this will also replace the current screen in the history
        const navigateCleanLinkWithParam = () =>
            navigate({
                routeName: 'user',
                params: { id: 'chris' }, // accessed with getParam and the location prop in the screen file
                web: { replace: true, to: '/profile' },
            })
    }

    For more thoughts on how and when you should use the web field, see Web Thoughts.

    getParam

    Same API as getParam from react-navigation, with an important difference.

    Important: The getParam function with gatsby is slightly less simple than the one offered by expo-next-react-navigation. You have to provide a fallback value as the second argument. This is because gatsby doesn't expose a hook to access the location.

    Example: src/pages/index.js

    export default function Screen({ location }) {
        const { getParam } = useRouting()
        // when on web, it will return the value for location.state.userId
        // web on mobile, it will use react-navigation
        const userId = getParam('userId', location.state.userId)
    }

    useFocusEffect

    See react navigation docs. On web, it simply replaces the focus effect with a normal effect hook. On mobile, it is the exact react navigation hook.

    Make sure to use useCallback as seen in the example below.

    import { useFocusEffect } from 'expo-gatsby-navigation'
     
    export default ({ userId }) => {
        useFocusEffect(
            useCallback(() => {
                const unsubscribe = API.subscribe(userId, user => setUser(user))
     
                return () => {
                    unsubscribe()
                }
            }, [userId])
        )
     
        return <Profile userId={userId} />
    }

    Link

    The following will use the chat route in react navigation.

    However, it will use the src/pages/room.js file for Gatsby.

    Optionally accepts a gatsbyLinkProps prop dictionary and touchableOpacityProps dictionary as well.

    export default function Button() {
        return (
            <Link
                routeName="chat"
                params={{ roomId: '12' }}
                web={{
                    to: '/room',
                    replace: false,
                }}
            >
                Chat in room 12
            </Link>
        )
    }

    Required props:

    Optional props

    • web: dictionary, see useRouting().navigate docs.

    • touchableOpacityProps: extends React Native's TouchableOpacity props.

    • gatsbyLinkProps: extends gatsby's Link props.

    Web Thoughts

    The web prop in the navigate function and Link component can help provide cleaner urls (user/mike instead of user?id=mike) on web.

    Also, navigation patterns on mobile can be different than web, and this field can help you account for those situations.

    For instance, imagine you have a tab navigator. Say the first tab has a nested stack navigator with an inbox screen and a chat room screen. If you navigate from a notifications tab to this tab, and a chat room screen was already open, you probably want that chat room to stay open on mobile. Only if you press the tab button a second time should it pop back to the inbox screen.

    This may not be the case on web. Web navigation patterns on web may lead you to want to open the inbox directly, instead of the open chat screen. This example could look something like this:

    navigate({
        routeName: 'inboxStack',
        web: {
            to: '/inbox',
        },
    })

    Keywords

    none

    Install

    npm i expo-gatsby-navigation

    DownloadsWeekly Downloads

    3

    Version

    0.0.8

    License

    MIT

    Unpacked Size

    29.8 kB

    Total Files

    43

    Last publish

    Collaborators

    • fernandorojo