0

Files:

App.js

import UserContext from "./userContext";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import './App.css';


//Importing components
import Registration from "./components/Registration";
import ProfileForm from "./components/ProfileForm";
import welcome from "./components/welcome";
import Navbar from "./components/Navigation"
import Form from "./components/Form";
import AllUsersList from "./components/AllUsersList";
import MainContent from "./components/MainContent";
import Users from "./components/Users";
import Ngos from "./components/Ngos";
import User from "./components/InfosUser";
import Ngo from "./components/InfosNgo";
import RouteForAll from "./components/RouteForAll";
import RouteOnlyForAdmins from "./components/RouteOnlyForAdmins";
import NoPermision from "./components/NoPermision";
import PageNotFound from "./components/PageNotFound";
import RedirectToNotFound from "./components/RedirectToNotFound";


const Main = () => {
  return (<div className="parent">
    <Navbar />
    <Switch>
      <RouteForAll exact path="/main" component={MainContent} />
      <RouteForAll path="/users" component={Users} />
      <RouteForAll path="/user/:id" component={User} />
      <RouteForAll path="/ngos" component={Ngos} />
      <RouteForAll path="/ngo/:id" component={Ngo} />
      <RouteOnlyForAdmins path="/usersList" component={AllUsersList} />
      <RouteForAll path="/profileform" component={ProfileForm} />
      <Route component={RedirectToNotFound} />
    </Switch>
  </div>)
}

const App = () => {
  const [user, setUser] = useState({});
  const [tokens, setTokens] = useState({});

  function loginTokens(tokens) {
    setTokens(tokens);
  }

  function loginUser(user) {
    setUser(user);
  }

  function logout() {
    setUser({});
    setTokens({});
  }

  return (
    <UserContext.Provider
      value={{
        user: user,
        tokens: tokens,
        loginTokens: loginTokens,
        loginUser: loginUser,
        logout: logout
      }}>
      <div className="parent">
        <Router>
          <Switch>
            <Route path="/notfound" component={PageNotFound} />
            <Route exact path="/" component={welcome} />
            <Route path="/login" component={Form} />
            <Route path="/register" component={Registration} />
            <RouteForAll path="/nopermision" component={NoPermision} />
            <Route component={Main} />
          </Switch>

        </Router>
      </div>
    </UserContext.Provider>
  );
};

export default App;

APIUtils.js

// this is our server and port address
// the base of all AJAX requests
const API_URL = "http://localhost:4321/";

export default class APIUtils {
  static async get(url, access_token) {
    return await issueAJAXRequest("GET", url, {}, access_token);
  }
  static async delete(url, access_token) {
    return await issueAJAXRequest("DELETE", url, access_token);
  }
  static async post(url, data, access_token) {
    return await issueAJAXRequest("POST", url, data, access_token);
  }
  static async put(url, data, access_token) {
    return await issueAJAXRequest("PUT", url, data, access_token);
  }
}

async function issueAJAXRequest(method, endpoint, body = {}, access_token = "") {
  const params = { method };
  params.headers = {
    "Authorization": `Bearer ${access_token}`
  };

  if (Object.keys(body).length > 0) {
    params.headers["Content-Type"] = "application/json; charset=utf-8";
    params.body = JSON.stringify(body);
  }

  const res = await fetch(API_URL + endpoint, params);
  if (!res.ok || res.status < 200 || res.status > 299) {
    const errorMessage = `HTTP ${res.status} - ${res.statusText}`;
    console.log(errorMessage);
    throw new Error(errorMessage);
  }
  return await res.json();
}

UserProvider.js


export default class UserProvider {
  static async getUsers(access_token) {
    return await APIUtils.get("users/", access_token);
  }
  static async getUser(id, access_token) {
    return await APIUtils.get(`users/${id}`, access_token);
  }
  static async createUser(userData) {
    return await APIUtils.post("users/", userData);
  }
  static async updateUser(id, userData, access_token) {
    return await APIUtils.put(`users/${id}`, userData, access_token);
  }
  static async deleteUser(id, access_token) {
    return await APIUtils.delete(`users/${id}`, access_token);
  }
  static async loginUser(userData) {
    return await APIUtils.post(`auth/login/`, userData);
  }
}

userContext.js


export const UserContext = React.createContext({
  user: {},
  tokens: {},
  loginTokens: tokens => {},
  loginUser: user => {},
  logout: () => {}
});

export default UserContext;

RouteForAll.js

import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import UserContext from "../userContext";
import UserProvider from "../UserProvider";

const RouteForAll = ({ component: Component, ...rest }) => {
    const user = useContext(UserContext);
    const accessTkn = localStorage.getItem('access_token')
    const refreshTkn = localStorage.getItem('refresh_token')

    async function checkUser() {

        try {
            let payload = JSON.parse(atob(accessTkn.split(".")[1]));
            const userData = await UserProvider.getUser(payload.id, accessTkn)
            if (userData.error) { throw userData.error };
            user.loginUser(userData);
            return true;
        }
        catch (anError) {
            console.log('Login Error:', anError);
        }
    }

    return <Route {...rest} render={(props) => {

        if (Object.keys(user.user).length &&
            (user.user.user.role === "admin" ||
                user.user.user.role === "user-independent" ||
                user.user.user.role === "user-ngo"
            )) { return <Component {...props} /> }

        else if (accessTkn && refreshTkn) {
            user.loginTokens({
                access_token: accessTkn,
                refresh_token: refreshTkn
            });
            if (checkUser()) { return <Component {...props} /> } else { return <Redirect to="/login" /> }
        }
    }} />
}

export default RouteForAll;

I tried with the code in RouteForAll but I've got the following error

"Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops."

Stef-Lev
  • 21
  • 2
  • Does this help? https://stackoverflow.com/questions/53453861/react-context-api-persist-data-on-page-refresh – displacedtexan Jul 29 '20 at 16:54
  • Unfortunately, I am not experienced enough to use it in my own code @displacedtexan – Stef-Lev Jul 29 '20 at 18:34
  • Basically you'll lose any data that's in React on page reload because it's not being saved anywhere. If you want to persist the data, you'll either need to save to localstorage or save to a db. – displacedtexan Jul 30 '20 at 14:04

0 Answers0