I am working on a app where I am using React as my front-end and React-apollo-graphql
for my API calling.
I am using react-hooks
i.e in React 16.8 +.
What I am doing
I have crated a auth.js
file where I am storing my values when user is loging in and also checking the token is it valid or not, (expiry I am checking), but that file is only loading my I am refreshing or reloading the page, That is not how it should work
My auth.js file
const initialstate = {
user: null,
};
if (localStorage.getItem("JWT_Token")) {
const jwt_Token_decoded = Jwt_Decode(localStorage.getItem("JWT_Token"));
console.log(jwt_Token_decoded.exp * 1000);
console.log(Date.now());
if (jwt_Token_decoded.exp * 1000 < Date.now()) {
localStorage.clear(); // this runs only when I refresh the page or reload on route change it dosent work
} else {
initialstate.user = jwt_Token_decoded;
}
}
const AuthContext = createContext({
user: null,
login: (userData) => {},
logout: () => {},
});
const AuthReducer = (state, action) => {
switch (action.type) {
case "LOGIN":
return {
...state,
user: action.payload,
};
case "LOGOUT":
return {
...state,
user: null,
};
default:
return state;
}
};
const AuthProvider = (props) => {
const [state, dispatch] = useReducer(AuthReducer, initialstate);
const login = (userData) => {
localStorage.setItem("JWT_Token", userData.token);
dispatch({
type: "LOGIN",
payload: userData,
});
};
const logout = () => {
localStorage.clear();
dispatch({ action: "LOGOUT" });
};
return (
<AuthContext.Provider
value={{ user: state.user, login, logout }}
{...props}
/>
);
};
export { AuthContext, AuthProvider };
As I have commented the line where I am checking the token expiry.
My only issue is why it is working on page reload not on each route like we do in store file when we use Redux.
My App.js
<AuthProvider>
<Router>
<div className="App wrapper">
<Routes/>
</div>
</Router>
</AuthProvider>
My index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import ApolloClient from 'apollo-boost'
import { ApolloProvider } from '@apollo/react-hooks';
import { InMemoryCache } from 'apollo-cache-inmemory';
const client = new ApolloClient({
uri: 'my url',
cache: new InMemoryCache(),
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById('root')
);
Important points
As I am using react-apollo-graphql
so do they provide ant Authentication flow ? like how redux does, we have to create a store file which will store our data
I am using React 16.8 + so I am using react-hooks so here I am using use Reducer
from that only.
My only question is am I doing it right? I am open to other approaches.
I have done authentication and authorization in Vue using Vuex there I use to create a store file which runs on ever route
Same I have done with Redux, In my store file I use to store the states and all.
Now if I am using react-hooks and react-apollo-graphql so no need to do this things with redux.
I am using apollo-link-context
for passing the header (Authorization) like below
const authLink = setContext(() => {
const token = localStorage.getItem('JWT_Token')
return {
headers:{
Authorization: token ? `${token}` : ''
}
}
});
I think here I can check on each route or on each request if the token is valid or not ( check exp time) if it is invalid then I will logout and clear my local storage, Clearing the storage is not a big deal the main thing is how to redirect to login page.