jankapunkt / meteor-react-native-starter

Boilerplate with auth, backend, db and many more! Clone, install, start coding!
https://dev.to/jankapunkt/meteor-and-react-native-create-a-native-mobile-app-2ile
MIT License
20 stars 5 forks source link

Use in combination with Expo router v3 #21

Open ma10as opened 7 months ago

ma10as commented 7 months ago

Describe the bug I have used the Auth logic from this repo for some time now without problems. Now i try to switch from React Navigation to Expo router v3 (file-based routing), and i ran into a issue.

On first load of the app the app doesn't run the handleOnLogin() function from useAuth. The app is never leaving the isLoading state before being reloaded.

I'm trying to follow this instruction https://docs.expo.dev/router/reference/authentication/#example-authentication-context

app/_layout.jsx

import { Slot } from 'expo-router';
import Constants from 'expo-constants';
import Meteor from '@meteorrn/core';
import AsyncStorage from '@react-native-async-storage/async-storage';

import { AuthContext } from '@/auth/AuthContext';
import { useAuth } from '@/auth/useAuth';

Meteor.connect(Constants.expoConfig?.extra?.meteorUrl, { AsyncStorage });

const Root = () => {
  const { authContext } = useAuth();

  return (
    <AuthContext.Provider value={authContext}>
      <Slot />
    </AuthContext.Provider>
  );
};

export default Root;

app/(app)/_layout.jsx

import { Text } from 'react-native';
import React from 'react';
import { useAuth } from '@/auth/useAuth';
import { Redirect, Stack } from 'expo-router';

const AppLayout = () => {
  const { state } = useAuth();
  const { userToken, isLoading } = state;

  if (isLoading) {
    return <Text>Loading...</Text>;
  }

  if (!userToken) {
    // On web, static rendering will stop here as the user is not authenticated
    // in the headless Node process that the pages are rendered in.
    return <Redirect href="/sign-in" />;
  }

  return <Stack />;
};

export default AppLayout;

useAuth.jsx

import { Alert } from 'react-native';
import Meteor from '@meteorrn/core';
import { router } from 'expo-router';

const initialState = {
  isLoading: true,
  isSignout: false,
  userToken: null,
};

const reducer = (state, action) => {
  switch (action.type) {
    case 'RESTORE_TOKEN':
      return {
        ...state,
        userToken: action.token,
        isLoading: false,
      };
    case 'SIGN_IN':
      return {
        ...state,
        isSignout: false,
        userToken: action.token,
      };
    case 'SIGN_OUT':
      return {
        ...state,
        isSignout: true,
        userToken: null,
      };
  }
};

const Data = Meteor.getData();

export const useAuth = () => {
  const [state, dispatch] = useReducer(reducer, initialState, undefined);

  useEffect(() => {
    console.log('useEffect');
    const handleOnLogin = () =>  dispatch({ type: 'RESTORE_TOKEN', token: Meteor.getAuthToken() });

    Data.on('onLogin', handleOnLogin);
    return () => Data.off('onLogin', handleOnLogin);
  }, []);

  const authContext = useMemo(
    () => ({
      signIn: ({ input, onError }) => {
        Meteor.loginWithPassword(input.email, input.password, async (err) => {
          if (err) {
            Alert.alert('Error', err.reason);
          }
          console.log('signIn - Compleate');
          const token = Meteor.getAuthToken();
          const type = 'SIGN_IN';
          dispatch({ type, token });
          router.replace('/');
        });
      },
      signOut: () => {
        Meteor.logout((err) => {
          if (err) {
            Alert.alert('Error', err);
          }
          dispatch({ type: 'SIGN_OUT' });
        });
      },
    }),
    []
  );
  return { state, authContext };
};

What could the problem be?

jankapunkt commented 7 months ago

Hi @ma10as thanks for reporting. Can you run Meteor.enableVerbose() and see what the console.info prints regarding the token? The onLogin will only run of the current token is found. I just want to make sure this is not an issue with the library. Also - which version of @meteorrn/core is currently installed at your project?

ma10as commented 7 months ago

Hi @jankapunkt I ran the Meteor.enableVerbose() function and the result is INFO Connected to DDP server. I use @meteorrn/core : "2.7.1"

jankapunkt commented 7 months ago

@ma10as I fixed a few things in the library and released 2.8.0, can you try this one first, please? Apart from that I will try to reproduce and see if the issue is actually related with the expo file router.

ma10as commented 7 months ago

@jankapunkt I will try to update to 2.8.0 and i will come back later today👍🏻

ma10as commented 7 months ago

Hi @jankapunkt i now updatet to 2.8.0 Now I am stuck on the loading page and it is not leaving it after reload. The Meteor.enableVerbose() now returns 3 results INFO Connected to DDP server., INFO User._loginWithToken::: token: ERtGkUfUhmiZBZ4GBfiPD_3F-FYspj5V4a_fT3yr4wG and INFO User._handleLoginCallback::: token: ERtGkUfUhmiZBZ4GBfiPD_3F-FYspj5V4a_fT3yr4wG id: Z8HiZDuqkzujLTzQT.

And it looks like the useReducer functions runs with the type RESTORE_TOKEN but the token: null