Render Error occurs when I launch react native app using expo go

121 views Asked by At

I am trying to implement a login authentication using Microsoft Account with 2 FA using Microsoft authenticator app for a project but I run into issues when testing the application. It will show me this error: Render Error. Couldn't find a navigation object. Is your component inside NavigationContainer?

I have tried searching for solutions online for that error but I could not find any that worked. Any help to fix the issue is appreciated. Thank you.

This is the first code I used but it did not work

 import React, { Component } from 'react';
 import { View, Button, Text } from 'react-native';
 import { UserAgentApplication } from 'react-native-msal';
 import { AuthenticationParameters } from 'react-native-msal';

 export default class Login extends Component {
   constructor(props) {
     super(props);
 
     this.auth = new UserAgentApplication({
       auth: {
         clientId: 'My_Client_ID',
         authority: 'My_Authority',
         redirectUri: 'exp://85-nny.anonymous.donewithit.exp.direct:80/--/auth', (I'm not sure if this redirect url is a valid one)
       },
     });
 
     this.state = {
       accessToken: null,
       userInfo: null,
     };
   }
 
   login = async () => {
     try {
       const authResult = await this.auth.login();
       const accessToken = authResult.accessToken;
 
       if (accessToken) {
         this.setState({ accessToken });
         this.getUserInfo();
       }
     } catch (error) {
       console.error(error);
     }
   }
 
   getUserInfo = async () => {
     try {
       const authParameters = new AuthenticationParameters();
       authParameters.scopes = ['openid', 'profile'];

       const userInfo = await this.auth.acquireTokenSilent(authParameters);
       this.setState({ userInfo });
     } catch (error) {
       console.error(error);
     }
   }
 
   logout = () => {
     this.auth.logout();
     this.setState({ accessToken: null, userInfo: null });
   }
 
   render() {
     const { accessToken, userInfo } = this.state;
 
     return (
       <View>
         {accessToken ? (
           <Button title="Logout" onPress={this.logout} />
         ) : (
           <Button title="Login with Microsoft" onPress={this.login} />
         )}
 
         {userInfo && (
           <View>
             <Text>Welcome, {userInfo.displayName}</Text>
             <Text>Email: {userInfo.userPrincipalName}</Text>
           </View>
         )}
       </View>
     );
   }
 }

export default Login;

This is the second code I tried after the first one did not work however, this one too also did not work.

import React from 'react';
import { View, Text, Button } from 'react-native';
import { authorize } from 'react-native-app-auth';
import { useNavigation } from '@react-navigation/native';
 
const Login = () => {
  const navigation = useNavigation();
 
  const config = {
    clientId: 'My_Client_ID',
    redirectUrl: 'exp://85-nny.anonymous.donewithit.exp.direct:80/--/auth',
    scopes: ['openid', 'profile', 'email', 'offline_access', 'User.Read'],
    serviceConfiguration: {
      authorizationEndpoint: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
      tokenEndpoint: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
    },
  };
 
  const loginWithMicrosoft = async () => {
    try {
      const result = await authorize(config);
 
      // If the user successfully logs in, navigate to the home page.
      if (result.idToken) {
        navigation.navigate('HomeScreen');
      }
    } catch (error) {
      console.error('Authentication Error:', error);
    }
  };
 
  return (
    <View>
      <Text>Login Page</Text>
      <Button title="Login with Microsoft" onPress={loginWithMicrosoft} />
    </View>
  );
};
 
export default Login;
1

There are 1 answers

6
Kadi On

The error isn't related to the contents of your Login component. It is saying that the component itself needs to be nested inside a navigation container. Something like this:

<NavigationContainer>
  <Stack.Navigator>
    <Stack.Screen name="Login" component={Login} />
  </Stack.Navigator>
</NavigationContainer>

If it's not inside the container, useNavigation will give you the error you're seeing.

Here, in the Login component you can use useNavigation, so you should have something like

const Login = () => {
  const navigation = useNavigation();
  const loginWithMicrosoft = () => {
    // code
  }

  return (
    <View>
      <Text>Login Page</Text>
      <Button title="Login with Microsoft" onPress={loginWithMicrosoft} />
    </View>
  )
}