Stack Exchange
User permissions in react
I am trying to implement user permissions with my react app.
UserContext
import axios from "axios";
import React, { createContext, useEffect, useState } from "react";


export const UserContext = createContext(null)

export const UserProvider = (props) => {
    const [token, setToken] = useState(localStorage.getItem("accessToken"));
    const [currentUser, setCurrentUser] = useState({});
    const [permissions, setPermissions] = useState([]);

    useEffect(() => {
        const getCurrentUser = () => {
            const headers = {
                headers: { Authorization: "Bearer " + token, }

            }

            axios.get("/api/users/me", headers)
                .then((res) => {
                    setCurrentUser(res.data);
                })
                .catch(() => {
                    setToken(null);
                    setCurrentUser({});
                })
                .finally(localStorage.setItem("accessToken", token))



        };
        getCurrentUser();
        const getPermissions = () => {
            if (currentUser.user_roles) {
                let perm = []
                for (let i = 0; i < currentUser.user_roles.length; i += 1) {
                    if (currentUser.user_roles[i].roles.role_permissions) {
                        for (let j = 0; j < currentUser.user_roles[i].roles.role_permissions.length; j += 1) {
                            perm.push(currentUser.user_roles[i].roles.role_permissions[j].permissions.name)
                        }
                    }
                }
                setPermissions(perm)
            }
        }
        getPermissions();
        console.log(permissions)
    }, [token]);



    return (
        <UserContext.Provider value={[[token, setToken], [currentUser, setCurrentUser], [permissions, setPermissions]]}>
            {props.children}
        </UserContext.Provider>
    )
}

useAuth hook
import { useContext } from "react";
import { UserContext } from "../contex/UserContex";

const useAuth = () => {
    return useContext(UserContext);
}
export default useAuth;

import { useEffect, useState } from "react";
import { useLocation, Navigate, Outlet } from "react-router-dom";
import useAuth from "../hooks/useAuth";

const RequireAuth = ({ allowedRoles }) => {
    const [[], [currentUser], [permissions]] = useAuth();
    const location = useLocation();

    /** 
        useEffect(() => {
            if (currentUser.user_roles) {
                let perm = []
                for (let i = 0; i < currentUser.user_roles.length; i += 1) {
                    if (currentUser.user_roles[i].roles.role_permissions) {
                        for (let j = 0; j < currentUser.user_roles[i].roles.role_permissions.length; j += 1) {
                            perm.push(currentUser.user_roles[i].roles.role_permissions[j].permissions.name)
                        }
                    }
                }
                setPermissions(perm)
            }
        }, [])
    
    */
    /** currentUser?.user_roles?.map((userRoles) => userRoles.roles?.role_permissions?.find(perm => allowedRoles?.includes(perm.permissions.name))) */

    return (

        allowedRoles.find((role) => permissions.includes(role))
            ? <Outlet />
            : currentUser?.username
                ? <Navigate to="/" state={{ from: location }} replace />
                : <Navigate to="/login" state={{ from: location }} replace />
    )
}

export default RequireAuth

Whenever I try this my app keeps re-rendering hundreds of times.
I tried getting the permissions in the RequiredAuth file as seen with the commented out code but this still did not work.
I cannot find a way to map through the permissions and get all the permission names and make the app show the outlet only if the allowedRoles is in the permission name.
By the way the structure of the user object is this:
{
  "username": "admin",
  "first_name": "admin",
  "last_name": "admin",
  "user_id": 1,
  "user_roles": [
    {
      "user_role_id": 1,
      "user_id": 1,
      "role_id": 1,
      "roles": {
        "name": "Admin",
        "role_id": 1,
        "role_permissions": [
          {
            "role_permission_id": 1,
            "role_id": 1,
            "permission_id": 1,
            "permissions": {
              "name": "admin:all",
              "permission_id": 1,
              "description": "Admin Privilages",
              "tag": "All"
            }
          }
        ]
      }
    }
  ]
}


Why does your useEffect has token as a dependency?

That is so everytime the token changes the current user will as well.

But this effect also changes the token. I guess that you should have two effects instead
