My own realtime chat with react, graphql and postgresql [part 8 - Routing and session token]
Tags: react, graphql, node
Published: 2020-11-03 15:45:46

As we saw in the [previous part](https://dev.to/dalejan/my-own-realtime-chat-with-react-graphql-and-postgresql-part-5-react-3309), 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](https://reactjs.org/docs/context.html#gatsby-focus-wrapper). 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*

```javascript

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*

```javascript
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;

```
1. The `authToken` variable is the token we'll get from the graphql mutations response.
2. The `handleAuthFlow` function will save or remove the token from the localstorage.
3. The `AuthContext.Provider` will provide our token and our `handleAuthFlow` 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*

```javascript
...
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:
1. With the `useContext` hook we can access the data provided from the AuthContext.
2. 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.
3. 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.
4. With the second `useEffect` hook we wait for the response of the `signInUser` 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*

```javascript
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;
```

1. Using the `handleAuthFlow` with a null param will erease the token from the local storage, and because of the `PrivateRoute` 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!!