我正在尝试将react迁移到react native,因为我想在制作网站之后制作应用程序,但是由于react-native的某些语法似乎与典型的react不同。我对react-native还是比较新手,所以我认为问题出在react-native处理令牌的方式上。Graphql查询和mutations似乎运行良好,但我的jwt令牌和身份验证似乎受到了影响。
代码
apolloClient.js
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;
auth.js
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 };
App.js
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>
);
}
错误信息:
如果您需要更多的代码,请让我知道并透明地编辑这篇文章。如果您不理解我的意思或想要表达的内容,请在下面发表评论,如果可以,请向我提供有关React Native的一些提示和建议,以便我可以更多地学习。谢谢!