Aayush Dahal
Aayush Dahal

Reputation: 1182

Unable to get redux state outside component

My redux state of auth user looks like:

auth:{
    user: {
            created_at: "2021-05-12T06:08:57.000000Z"
            email: "[email protected]"
            id: 1
            name: "John Doe"
            permissions: ["product-view", "product-create", "product-update", "product-destroy", "category-view",…]
            role: "superAdmin"
            role_id: 1
            updated_at: "2021-05-12T06:08:57.000000Z"
    }
}

And I am trying to check if user have permission or not using this permission array. For that I have created a utility fileauthUser.js and looks like:

import _ from "lodash";

import { store } from "../store";

let adminRole = ["superAdmin", "admin"];
const state = store.getState();
const currentUser = state.auth.user;

export async function havePermission(permission) {
    console.log("currentUser >>", currentUser);
    console.log("permission >>", permission);
    if (isAdmin()) {
        return true;
    }
    if (_.includes(currentUser.permissions, permission)) {
        return true;
    }
}

export async function isAdmin() {
    if (adminRole.includes(currentUser.role)) {
        return true;
    }
}

export default {
    isAdmin,
    havePermission,
};

and I am calling this function from
sidebar.jsx

import authUser from "../../../utils/authUser";

const Sidebar = () => {
    return(

        <div>
            {console.log(` have permission called >>
                ${authUser.havePermission("product-view")}
            `)}
            {authUser.havePermission("view-name") &&
                "Dummy Name"}
        </div>

    )
}

and i am exporting store as export { persistor, store };

currently these data are showing up on console.log

currentUser >> {}
permission >> product-view
have permission called >> [object Promise]                      
currentUser >> {}
permission >> view-name

Unable to find, why currentUser is an empty object. How could I solve this permission check, as it currently it is returning empty object, although I can clearly see this user object on redux tab with values.

Upvotes: 0

Views: 147

Answers (1)

ljbc1994
ljbc1994

Reputation: 2244

In your utility file, the call to getState() will only be called initially so whenever you try to access the currentUser you will have the default state without any updates that have been applied since.

const state = store.getState();
const currentUser = state.auth.user;

You'll want to move the above call into a selector which will be given the current state and work out whether the current user has the permission, i.e.

export async function havePermission(state, permission) {
    console.log("currentUser >>", state.auth.user);
    console.log("permission >>", state.auth.user.permissions);
    if (isAdmin(state.auth.user)) {
        return true;
    }
    if (_.includes(state.auth.user.permissions, permission)) {
        return true;
    }
    return false;
}

You can use the useSelector hook from react-redux which will pass through the current redux state, you can then pass this to havePermission to figure out whether the user has the specific permission.

import { useSelector } from "react-redux";
import {havePermission} from "../../../utils/authUser";

const Sidebar = () => {
    const hasProductPermission = useSelector((state) => havePermission(state, "product-view"));
    const hasViewNamePermission = useSelector((state) => havePermission(state, "view-name"));

    return(

        <div>
            {console.log(` have permission called >>
                ${hasProductPermission}
            `)}
            {hasViewNamePermission &&
                "Dummy Name"}
        </div>

    )
}

Additionally, you could move the useSelector call into a custom permissions hook:

import { useSelector } from "react-redux";
import { havePermission } from "../../../utils/authUser";

const usePermission = (permission) => {
   return useSelector((state) => havePermission(state, permission);
}
const Sidebar = () => {
    const hasProductPermission = usePermission("product-view");
}

Upvotes: 1

Related Questions