1
votes

I have an app built with React-Native, Amplify, AppSync and Cognito and when it loads I would like to save the USER ID and USER TYPE as a global state that can be accessed on every screen.

The user id and user type (Teacher or Student) will never change as these are created on signup.

import React, { useEffect, useState, useReducer } from 'react';
import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';
import App from './src/AppNavigation';

import Amplify, { API, graphqlOperation, Auth } from 'aws-amplify';
import awsmobile from './aws-exports';

import { getUser } from './src/graphql/queries';

Amplify.configure(awsmobile);

export const UserContext = React.createContext()

function MyApp() {
  const [userContext, setUserContext] = useState({})

  const getUserIdAndType = async () => {
    try {
      // get User data
      const currentUser = await Auth.currentAuthenticatedUser();
      const userId = await currentUser.signInUserSession.accessToken.payload.sub;

      // get user data from AppSync
      const userData = await API.graphql(graphqlOperation(getUser, { id: userId }));
      
      setUserContext({ userId: userId, userType: userData.data.getUser.userType })
    
    } catch (err) {
      console.log('error', err);
  }
}
  
  useEffect(() => {
    getUserIdAndType()
  }, [])


  return (
    <UserContext.Provider value={userContext}>
      <App />
    </UserContext.Provider>
  );
}

AppRegistry.registerComponent(appName, () => MyApp);

Then when I want to use the context state I do as follows:

import { useContext } from 'react';
import { UserContext } from '../../../index';


function Loading ({ navigation }) {
    const userContext = useContext(UserContext)

    if (userContext.userId != '') {
        navigation.navigate('AppTabs');
    } else {
        navigation.navigate('Auth');
    }
}

export default Loading;

Or to get which screen to show (Teacher or Student)...

import { useContext } from 'react';
import { UserContext } from '../../../index';

function LoadingProfile ({ navigation }) {
  const userContext = useContext(UserContext)

    if (userContext.userType === 'Teacher') {
      navigation.navigate('TeacherScreen');
    } else if (userContext.userType === 'Student') {
      navigation.navigate('StudentScreen');
    }
}

export default LoadingProfile;

When the app loads it says the userContext.userId and userContext.userType are empty so it is not saving the state when I set it in the getUserIdAndType() function.

-

****** If I rewrite the App file (INSTEAD OF USING THE HOOKS useState, useEffect) I just declare the values then it works... so I am obviously not using the hooks or async getUserIdAndType() correctly. ******

import React, { useEffect, useState, useReducer } from 'react';
import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';
import App from './src/AppNavigation';

import Amplify, { API, graphqlOperation, Auth } from 'aws-amplify';
import awsmobile from './aws-exports';

import { getUser } from './src/graphql/queries';

Amplify.configure(awsmobile);

export const UserContext = React.createContext()

function MyApp() {

   const userContext = {
     userId: '123456789', // add the user id
     userType: 'Teacher', // add the user type
   }


  return (
    <UserContext.Provider value={userContext}>
      <App />
    </UserContext.Provider>
  );
}

AppRegistry.registerComponent(appName, () => MyApp);
1

1 Answers

0
votes

change this :

<UserContext.Provider value={{userContext}}>
  <App />
</UserContext.Provider>

to this :

<UserContext.Provider value={userContext}>
  <App />
</UserContext.Provider>

you've added an extra curly bracket " { "