As we saw in the previous part, we were able to execute the sign in mutation (i hope you tried to build the sign up mutation by your self, in any case at the end i will post the repo ;)).
Now in this part we'll see how to use the routing system programmatically in react and how to store in the local storage the user's token.
First of all we need to provide a way to access the session from any component inside the app, so we dont have to repeat a lot of code i propose to use context API. If you have another idea in order to achive the global session access let me know in the comments!
For this, lets create our auth context.
./utils/Auth.context.js
import React from "react";
const AuthContext = React.createContext();
export default AuthContext;
Now we can provide this context to all our components.The goal using context is to get the token authetication value that's updated in our database every sign in and sign up for each user.
This token has to be persisten in order to remember our login even if we close the app. For this we'll use localstorage.
Let's see that in the code:
./App.jsx
import { ApolloProvider } from "@apollo/client";
import React, { useState } from "react";
import { HashRouter } from "react-router-dom";
import AppRouter from "./AppRouter";
import { client } from "./graphql/client";
import appRoutes from "./routes/app.routes";
import AuthContext from "./utils/Auth.context";
const App = () => {
const [authToken, setAuthenticated] = useState(null);
const handleAuthFlow = (authToken) => {
setAuthenticated(authToken);
if (authToken) {
localStorage.setItem("authToken", JSON.stringify(authToken));
} else {
localStorage.removeItem("authToken");
}
};
return (
<div className="App">
<AuthContext.Provider value={{ authToken, handleAuthFlow }}>
<ApolloProvider client={client}>
<HashRouter basename="/">
<AppRouter routes={appRoutes} />
</HashRouter>
</ApolloProvider>
</AuthContext.Provider>
</div>
);
};
export default App;
- The
authToken
variable is the token we'll get from the graphql mutations response. - The
handleAuthFlow
function will save or remove the token from the localstorage. - The
AuthContext.Provider
will provide our token and ourhandleAuthFlow
so we dont repeat a lot of code.
Now with this setup we can access the provider from our login container.
./containers/Login/Login.jsx
...
const Login = (props) => {
...
const { handleAuthFlow } = useContext(AuthContext);
const [submitted, setSubmitted] = useState(false);
useEffect(() => {const authToken = JSON.parse(localStorage.getItem("authToken"));
if (authToken) {
props.history.push("/chatroom");
}
}, [props.history]);
useEffect(() => {
if (!loading) {
if (data?.signInUser.usr) {
handleAuthFlow(data.signInUser.token);
props.history.push("/chatroom");
} else if (submited) {
console.log("nope");
setSubmitted(false);
}
}
}, [data, loading, handleAuthFlow, props.history, submitted]);
const onSubmitSignin = (fields) => {
signInUser({
variables: { usr: fields.username, password: fields.password }});
setSubmitted(true);
};
...
}
...
Let's explain the changes:
- With the
useContext
hook we can access the data provided from the AuthContext. - The
submited
flag will allow us to check when the form was submitted so we can show messages in case the mutation response comes empty. - Using the first
useEffect
hook we can 'watch' over a state, so if the token is saved we navigate to the Chatroom container using the history from the react-router provider. - With the second
useEffect
hook we wait for the response of thesignInUser
mutation, and then decide if navigate or show a message.
So now we can actually login, but let's also setup the logout:
./containers/Chatroom/Chatroom.jsx
import React, { useContext } from "react";
import AuthContext from "../../utils/Auth.context";
const Chatroom = () => {
const { handleAuthFlow } = useContext(AuthContext);
const logout = () => {
handleAuthFlow(null);
};
return (
<div>
chatroom
<p onClick={logout}>logout</p>
</div>
);
};
export default Chatroom;
- Using the
handleAuthFlow
with a null param will erease the token from the local storage, and because of thePrivateRoute
HOC we'll see the automatic redirection to the login container!
And that's it, we have an authentication flow with graphql and react, in the next part we'll be setting the real time chat!!
Top comments (0)