Search code examples
reactjsreduxreact-hooksreact-reduxredux-toolkit

React HOC not rendering propery based on conditions from hook


I have a React component made for hiding or showing content depending on the user's permissions. The permissions are received from a API via a hook created with redux toolkit and RTK Query API.

Permission.tsx:

import type { ReactElement } from 'react';
import { useHasPermissionQuery } from '~/common/authSlice';

type PermissionProps = {
    action: string;
    resource: string;
    element?: React.ReactNode | null;
};
const Permission = ({ action, resource, element }: PermissionProps): ReactElement | null => {
    const {
        data: hasPermission,
        isError,
        isFetching,
    } = useHasPermissionQuery({
        action: action,
        resource: resource,
    });

    console.log(`${resource}.${action}: ${hasPermission ?? false ? 'yes' : 'no'}`);

    if (hasPermission === undefined || !hasPermission || isError || isFetching) {
        return <div>Not allowed</div>;
    }

    return <>{element}</>;
};

export default Permission;

The component is used like this, with the ApiProvider from redux toolkit. I haven't configured any custom stores.:

const domContainer = document.getElementById('view-main')!;
const root = ReactDOM.createRoot(domContainer);
root.render(
    <ApiProvider api={api}>
        <Permission
            action="dummyAction"
            resource="dummyResource"
            element={<div>Is this allowed?</div>}
        />
    </ApiProvider>
);

authSlice.ts:

import { api } from '~/features/posts/postsSlice';
export type Permission = boolean;

export type PermissionRequest = {
    action: string;
    resource: string;
};

export const api = api.createApi({
    baseQuery: fetchBaseQuery({
        baseUrl: '/',
    }),
    endpoints: (build) => ({
        hasPermission: build.query<Permission, PermissionRequest>({
            query: ({ action, resource }) =>
                `authorization/testpermission/?requestedAction=${action}&resource=${resource}`,
        }),
    }),
});

export const { useHasPermissionQuery } = extendedApiSlice;

This is the console log of the Permission component. The final log says that the user has the permission, but that's not what the network log says, as you can see in the other picture. enter image description here

enter image description here

So I'm not sure what's happening here. Everything from the server is fine, so is it the hooks or the component where something is not right?


Solution

  • I think your hasPermission variable is the complete response of the server (instead of the boolean value you are expecting in your code):

    console.log(hasPermission) // { hasPermission: false }
    

    Use the correct value using:

        const {
            data,
            isError,
            isFetching,
        } = useHasPermissionQuery({
            action: action,
            resource: resource,
        });
    
        const hasPermission = data.hasPermission
    

    Or same, using double destructuring:

        const {
            data: { hasPermission },
            isError,
            isFetching,
        } = useHasPermissionQuery({
            action: action,
            resource: resource,
        });