My React Native app crashes during Login and Logout ( when context is changed ) - react-native

I have a react native app and whenever I try to login or logout the app crashes .. I am not getting any error logs in React Native Debugger.
so the App Crashes and then when I reopen the app the changes have already taken effect ( i.e :- If I was trying to login I would be logged in when I reopen the app)
I have 2 files for Navigation
CofficNavigator.tsx
// This file has all the routing
// here BottomNavigator is a tab Navigator and AuthNavigator is a stack navigator
// Before the app crashing all the correct state is set but it just crashes
// ----------- Final Stack Navigator ----------------
const FinalStackNavigator = createStackNavigator();
export const FinalNavigator = (props: any) => {
const authContext = useContext(AuthContext);
const [signedIn, setSignedIn] = useState<boolean | null>(
authContext.isLoggedIn
);
useEffect(() => {
if (authContext.isLoggedIn !== signedIn && !authContext.isLoading) {
setSignedIn(authContext.isLoggedIn);
}
}, [authContext]);
return (
<FinalStackNavigator.Navigator>
{signedIn ? (
<>
<FinalStackNavigator.Screen
name="BottomNavigator"
component={BottomNavigator}
options={{ headerShown: false }}
/>
</>
) : (
<>
<FinalStackNavigator.Screen
name="AuthNavigator"
component={AuthNavigator}
/>
</>
)}
</FinalStackNavigator.Navigator>
);
};
AppNavigator.tsx
export const AppNavigator = (props: any) => {
return (
<NavigationContainer>
<FinalNavigator />
</NavigationContainer>
);
};
-------- Login Logic flow -------------
on success of login API I call this line
await authContext.changeCofficToken(result.data.login.token);
AuthContext.ts
const changeCofficToken = async (token: string) => {
await setItem("cofficToken", token);
setIsLoggedIn(true);
setCofficToken(token);
};
helper.ts
export const setItem = async (key: string, value: any) => {
await AsyncStorage.setItem(key, value);
};
App.tsx
return (
<AuthContextProvider>
<FilterContextProvider>
<SearchTermContextProvider>
<ShowVerticalListContextProvider>
<CouponContextProvider>
<ApolloProvider client={client}>
<AppNavigator />
</ApolloProvider>
</CouponContextProvider>
</ShowVerticalListContextProvider>
</SearchTermContextProvider>
</FilterContextProvider>
</AuthContextProvider>
);
------ End of Login Logic code flow -------
Error logs from my IOS Simulator
com.apple.CoreSimulator.SimDevice.957FA264-501C-44C3-80F3-9E8D1F600A1E[15500] (UIKitApplication:host.exp.Exponent[e036][rb-legacy][15601]): Service exited due to SIGABRT
assertion failed: 19F101 17F61: libxpc.dylib + 83746 [ED46009E-B942-37CC-95D4-82CF3FE90BD8]: 0x7d
Please Note :- I am using Expo if it matters
Video Link :- https://fisico-dhaval.s3.ap-south-1.amazonaws.com/Screen+Recording+2020-08-20+at+5.38.06+PM.mov
If you need any other code snippets then please do lemme know
Any help will be appreciated

Can you share the code where you setSignin. In case if you are saving and clearing token, make sure those libraries are supported and linked properly.

Service exited due to SIGABRT is a common issue in Native iOS development, it can be cause due to various events. While working on react-native, I have never experienced this error. But I'm adding some of my observation, may be that can help you,
This can be cause due to some buggy component, which are not compatible with Expo version. So, you need to add many console.log or may be comment some things and check is there any functionality or a component causing this error. A buggy component can be a culprit.
If you have pod installed, Make sure you check all your libraries.You likely have some issue with an installed external library. and make sure you run pod install and delete node_modules folder and then run npm install again (close the packager too)
You can also use sentry or any other crash reporting library to detect crashes, It will give you the exact line number.
Sometimes the crash reporting libraries won't work, the reason can be that the crash occurs before the js bundle is loaded and because of that, the library is not yet initialised and it can't detect the crash. If so you can install a native crash reporting library, You can use fabric for that, or even bugsnag.
These are few scenarios, I've observed via which you can debug or detect what's the real cause of this error.

Related

apollo-client: makeVar / useReactiveVar can be updated from another screen?

I use react-native with apollo-client3.
In my App.js file that starts my project, I configure if I log in go to LoggedInNav else LoggedOutNav.
<ApolloProvider client={client}>
<NavigationContainer>
<View onLayout={onLayoutRootView}></View>
{isLoggedIn ? <LoggedInNav /> : <LoggedoutNav />}
</NavigationContainer>
</ApolloProvider>
And the state whether I log in or not is tracked from useReactiveVar.
const isLoggedIn = useReactiveVar(isLoggedInVar);
In my LogIn.js file, I do log in and if it succeeds, I update my isLoggedInVar state made from makeVar of apollo/client from false to true.
export const isLoggedInVar = makeVar(false);
export const tokenVar = makeVar("");
export const logUserIn = async (token) => {
try {
await AsyncStorage.setItem("token", JSON.stringify(token));
isLoggedInVar(true);
tokenVar(token);
} catch (e) {
console.error(e);
}
};
So I update my state of makeVar in another screen, but can App.js listen to this update and navigate from <LoggedInNav/> to <LoggedOutNav/>?
I think App.js file is the bottom of all screens of my app, it should work.
But in my app project, I feel sometimes it might works but sometimes it throws Network error.
And in this case How can I make switch between two Navs according to Login state? Please help me.

Expo-Auth session is not working properly

While implementing google login using the expo-auth-session package , I am getting some error that i don't have any idea about, It has been more than one day since i am stuck in this problem i cannot find a reliable source to use for implementing google login in my expo application. Is there any other way i can implement it in the react native expo application.
The error i am getting are :
WARN Linking requires a build-time setting `scheme` in the project's Expo config (app.config.js or app.json) for production apps, if it's left blank, your app may crash. The scheme does not apply to development in the Expo client but you should add it as soon as you start working with Linking to avoid creating a broken build. [Learn more][1]:
WARN EventEmitter.removeListener('url', ...): Method has been deprecated. Please instead use `remove()` on the subscription returned by `EventEmitter.addListener`.
WARN Possible Unhandled Promise Rejection (id: 2):
Error: Exception in HostFunction: Malformed calls from JS: field sizes are different.
What should i do ??
The link to the documentation that i followed is :-
And this is what i used from the documentation.
import * as Google from "expo-auth-session/providers/google";
import * as WebBrowser from "expo-web-browser";
WebBrowser.maybeCompleteAuthSession();
const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId: expoClientId,
});
const login = ()=>{
useEffect(() => {
if (response?.type === "success") {
const { authentication } = response;
console.log(authentication);
}
}, [response]);
return (
<Pressable style={styles.btn} onPress={promptAsync}>
<Image
source={require("../../../assets/g1.png")}
style={styles.img}
/>
<Text style={styles.text}>Sign in with Google</Text>
</Pressable>
)
}
thank you any help would be appriciated.
In your app.json add following
"scheme":"com.yourpackage.yourapp"
this value must be same as your android.package and ios.bundleIdentifier

useURL hook expo-linking for background app

The expo-linking React Native package has a hook named useURL that isn't working for me when the app is in the background. From the docs it Returns the initial URL followed by any subsequent changes to the URL. The problem I'm having with my managed expo app is that the hook doesn't work when the app is already open in the background. Here is the hook:
export default function App() {
const isLoadingComplete = useCachedResources();
const url = Linking.useURL();
useEffect(() => {
Alert.alert(url ? url.substring(20) : 'null');
}, [url]);
if (!isLoadingComplete) {
return null;
} else {
return (
...
);
}
}
If I open the URL exp://exp.host/#myprofile/myproject?a=bwhen the app is closed, I get an Alert as expected. If the app is in the background, the Alert doesn't go off. I've tested on an iOS emulator and a physical Android. Any solutions? Note that similar problems happen with Linking.addEventListener().

Deep linking launches the app, but handles the external url wrongly

I am developing an React Native project, using React-Navigation v5.
I now try to implement deep linking feature. I followed the official instruction set up deep linking successfully (I mean the app is launched by custom url scheme). Next I need to handle the external link, my issue comes at this point.
To handle external link in my react-native project, I also followed the instruction configure links.
I defined a linking.js in my project:
const config = {
screens: {
// I explained why I nest FooScreen like this if you continue reading
FeatureFlow: {
SubfeatureFlow: {
FooScreen: {
path: 'foo/:myId',
},
},
},
},
};
const linking = {
prefixes: ['myapp://mobile'],
config,
};
export default linking;
Then, in my NavigationContainer, I use the linking as below:
return (
<NavigationContainer
linking={linking}
...
>
<MainFlow />
</NavigationContainer>
As you can see above, three things worth a notice:
in linking.js, inside config I specified that the path e.g. foo/123 should open screen FooScreen.
The FooScreen is a nested screen.
NavigationContainer contains a component called MainFlow.
To illustrated how FooScreen is nested in navigation hierarchy, let's start with MainFlow, which looks like this:
const MainFlow = ({navigation}) => {
const Drawer = createDrawerNavigator();
return (
<Drawer.Navigator
...>
<Drawer.Screen name="FeatureFlow" component={MyFeatureFlow} />
...
</Drawer.Navigator>
);
};
As you can see, MainFlow is a DrawerNavigator which hosts a screen named FeatureFlow refers to component MyFeatureFlow.
And MyFeatureFlow looks like this:
const MyFeatureFlow = ({navigation}) => {
const FeatureStack = createStackNavigator();
return (
<FeatureStack.Navigator
...>
<FeatureStack.Screen
name="SubfeatureFlow"
component={MySubfeatureFlow}/>
</FeatureStack.Navigator>
)
As you can see above, FeatureFlow is a stack navigator which hosts a screen named SubfeatureFlow, refers to component MySubfeatureFlow.
And MySubfeatureFlow is like:
const MySubfeatureFlow = ({navigation}) => {
const SubfeatureStack = createStackNavigator();
return (
<SubfeatureStack.Navigator
...>
<SubfeatureStack.Screen
name="FooScreen"
component={MyFooScreen}
</SubfeatureStack.Navigator>
)
As you can see above, MySubfeatureFlow is another stack navigator which hosts a screen named FooScreen refers to component MyFooScreen.
Now you understand why in linking.js configuration, the FooScreen is nested like that.
Then, I run my app on iOS simulator. The app launched. I killed the app on simulator.
Then, I run command npx uri-scheme open myapp://mobile/foo/123 --ios. (I also tried open mobile browser, type in url myapp://mobile/foo/123, same error as below)
I see on simulator, the app is launched by the command, which means my deep linking is set up. However, handling external link to open FooScreen fails, I end up with the following error:
The error tells me the navigation payload tries to treat 123 as screen, and the app treat foo as name of the screen in my project. I completely don't understand why it is. Is there something wrong with my linking configuration?

Preloading assets in React-Native expo app never finishes

I'm writing a simple app with React Native and Expo.
This app has ~10 small to medium sized images that are used in different places within the app.
From what I read, unless I cache these images, they will be required to be downloaded from expo each time.
For this reason, I have noticed that they seem to load in really slowly when testing the app. Upon building and navigating through the app, I find that it takes a few seconds for my images to pop up even after the rest of the page has loaded.
I followed the setup as seen in the starting template.
Here is what my App.js looks like (I am using react-navigation so it varies from the sample file above):
export default class App extends React.Component {
state = {
isLoadingComplete: false
};
componentDidMount() {
StatusBar.setHidden(true);
}
render() {
_loadResourcesAsync = async () => {
return Promise.all([
Asset.loadAsync([
require("./assets/syria.png"),
require("./assets/lebanon.png"),
require("./assets/kenya.png"),
require("./assets/indonesia.png"),
require("./assets/somalia.png"),
require("./assets/india.png"),
require("./assets/america.png"),
require("./assets/albania.png"),
require("./assets/bosnia.png")
])
]);
};
_handleLoadingError = error => {
Alert.alert(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
if (this.state.isLoadingComplete == false) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<AppContainer
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
);
}
}
}
I have excluded my react-navigation code for the sake of brevity.
When I run this, my app gets stuck at Downloading JavaScript bundle 100.00%.
It seems that the _handleFinishLoading never runs. At least, that's the only reason I can see for it to never finish loading.
Given the small amount of images, I don't know how this could take more than a second. Instead it sits at the splash screen forever.
Any ideas on what I might be doing wrong here?
Found the solution:
I made a simple error. The async functions (_loadResourcesAsync, _handleFinishLoading, etc) need to be outside the render method. Moving them below my render method inside of the app class caused this to work as expected.