I am trying to migrate react to react native since I want to make an application next after I made the website, but since some syntaxes of react-native seems to be different than typical react. I am just fairly new to react-native, so I think the problem is with the way react-native handle token. Graphql queries and mutations seems to be working fine but my jwt token and authentication seems to take a hit.
import { ApolloClient } from "@apollo/client/core";
import { InMemoryCache } from "@apollo/client/cache";
import { setContext } from "@apollo/client/link/context";
import { createUploadLink } from "apollo-upload-client";
import AsyncStorage from "@react-native-async-storage/async-storage";
const httpLink = createUploadLink({
uri: "http://localhost:5001/graphql",
});
const authLink = setContext(async () => {
const token = await AsyncStorage.getItem("jwtToken");
return {
headers: {
Authorization: token ? `Bearer ${token}` : "",
},
};
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
export default client;
import { useReducer, createContext, useEffect } from "react";
import jwtDecode from "jwt-decode";
import AsyncStorage from "@react-native-async-storage/async-storage";
const initialState = {
user: null,
};
const getToken = async () => {
try {
const storedToken = await AsyncStorage.getItem("jwtToken");
if (storedToken !== null) {
const decodedToken = jwtDecode(AsyncStorage.getItem("jwtToken"));
const expirationData = decodedToken.exp;
const currentDate = Date.now / 1000;
if (expirationData >= currentDate) {
initialState.user = decodedToken;
}
}
} catch (err) {
console.log(err);
}
};
getToken();
const AuthContext = createContext({
user: null,
login: (userData) => {},
logout: () => {},
});
function authReducer(state, action) {
switch (action.type) {
case "LOGIN":
return {
...state,
user: action.payload,
};
case "LOGOUT":
return {
...state,
user: null,
};
default:
return state;
}
}
function AuthProvider(props) {
const [state, dispatch] = useReducer(authReducer, initialState);
// const router = useRouter();
function login(userData) {
AsyncStorage.setItem("jwtToken", userData.token);
dispatch({
type: "LOGIN",
payload: userData,
});
}
function logout() {
AsyncStorage.removeItem("jwtToken");
// toast.error("Logged out successfully", shortToastConfig);
dispatch({ type: "LOGOUT" });
}
useEffect(() => {
if (state.user) {
const decodedToken = jwtDecode(AsyncStorage.getItem("jwtToken"));
const timeLeft = decodedToken.exp * 1000 - Date.now();
setTimeout(() => {
dispatch({
type: "LOGOUT",
});
AsyncStorage.removeItem("jwtToken");
// toast.error("Session Expired", shortToastConfig);
// router.push("/login");
}, timeLeft);
}
}, [state]);
return (
<AuthContext.Provider
value={{ user: state.user, login, logout }}
{...props}
/>
);
}
export { AuthContext, AuthProvider };
import React from 'react';
import { ApolloProvider } from '@apollo/client';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useFonts } from 'expo-font';
import {
MyShop,
SignIn,
SignUp,
Navigator,
Chats,
ShoppingCart,
Settings,
// Country,
Me,
Home,
Categories,
SubCategories,
Products,
} from './screens';
import { AuthProvider } from './context/auth';
import client from './context/apolloClient';
export default function App() {
LogBox.ignoreAllLogs(true);
const Stack = createStackNavigator();
return (
<ApolloProvider client={client}>
<AuthProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={{ headerShown: false }}
initialRouteName="Navigator"
>
<Stack.Screen
name="Navigator"
component={Navigator}
options={{ gestureEnabled: false }}
/>
<Stack.Screen
name="Home"
component={Home}
options={{ gestureEnabled: false }}
/>
{/* <Stack.Screen
name="Country"
component={Country}
options={{ gestureEnabled: false }}
/> */}
<Stack.Screen
name="SignIn"
component={SignIn}
options={{ gestureEnabled: false }}
/>
<Stack.Screen
name="SignUp"
component={SignUp}
options={{ gestureEnabled: false }}
/>
<Stack.Screen
name="Me"
component={Me}
options={{ gestureEnabled: false }}
/>
<Stack.Screen name="MyShop" component={MyShop} />
<Stack.Screen name="ShoppingCart" component={ShoppingCart} />
<Stack.Screen name="Chats" component={Chats} />
<Stack.Screen name="Settings" component={Settings} />
{/* Other Pages */}
<Stack.Screen name="Categories" component={Categories} />
<Stack.Screen name="SubCategories" component={SubCategories} />
<Stack.Screen name="Products" component={Products} />
</Stack.Navigator>
</NavigationContainer>
</AuthProvider>
</ApolloProvider>
);
}
Error Shown:

If you need more code I can be transparent and edit this post, and if u don't understand what I mean or trying to point out please comment down below if you can, and if you would be kind enough also to give me some few tips and advice on react-native so I could learn more about it. Thank you!!
AsyncStorage functions that you are using are asynchrounous functions. You will have to wait for them to be resolved.
Usage:
const getData = async () => {
try {
const value = await AsyncStorage.getItem('@storage_Key')
if(value !== null) {
// value previously stored
}
} catch(e) {
// error reading value
}
}
// In your case the key is `jwtToken`
const token = await AsyncStorage.getItem("jwtToken");
More info and source here:
https://react-native-async-storage.github.io/async-storage/docs/usage
Try to make your code work with a hardcoded JWT token and then add the async storage functionality.
You need to wait to resolve the Promise when getting something from AsyncStorage.
In AuthProvider change useEffect to
useEffect(() => {
if (state.user) {
logout();
}
}, [state]);
where
const logout = async () => {
const decodedToken = jwtDecode(await AsyncStorage.getItem("jwtToken"));
const timeLeft = decodedToken.exp * 1000 - Date.now();
setTimeout(() => {
dispatch({
type: "LOGOUT",
});
AsyncStorage.removeItem("jwtToken");
// toast.error("Session Expired", shortToastConfig);
// router.push("/login");
}, timeLeft);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With