Last active
December 1, 2020 11:33
-
-
Save wintondeshong/1d052ade01c8323389aac9b1e67da16b to your computer and use it in GitHub Desktop.
React Hook Refactoring
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---------------------------------------------------- | |
// This is the original react hook before refactoring | |
// ---------------------------------------------------- | |
import IdentityRecord from "models/view-models/identity-record"; | |
import UserLoginRecord from "models/view-models/user-login-record"; | |
import { useCallback } from "react"; | |
import RoleService from "utilities/services/role-service"; | |
import UserRoleService from "utilities/services/users/user-roles/user-role-service"; | |
import UserService from "utilities/services/user-service"; | |
import UserLoginService from "utilities/services/user-logins/user-login-service"; | |
/** | |
* Custom hook providing utility functions for the current login of the user | |
*/ | |
export default function useIdentity() { | |
const { get: getUserApi } = UserService.useGet(); | |
const { get: getUserLoginApi } = UserLoginService.useGet(); | |
const { list: listUserRolesApi } = UserRoleService.useList(); | |
const { list: listRolesApi } = RoleService.useList(); | |
/** | |
* Build the identity record including the current User, UserLogin and UserRoles | |
* | |
* @param {UserLoginRecord|undefined} (userLogin | |
* @returns Promise | |
*/ | |
const buildCurrentIdentity = useCallback( | |
(userLogin: UserLoginRecord | undefined) => { | |
const getIdentity = async ( | |
userLogin: UserLoginRecord | |
): Promise<IdentityRecord | undefined> => { | |
const userLoginResponse = await getUserLoginApi({ | |
id: userLogin.id!, | |
}); | |
const userResponse = await getUserApi({ | |
id: userLogin.userId!, | |
}); | |
const rolesResponse = await listRolesApi(); | |
const userRolesResponse = await listUserRolesApi({ | |
userId: userLogin.userId!, | |
}); | |
if (userResponse.result!.hasErrors()) { | |
return; | |
} | |
const updatedUserLogin = userLoginResponse.resultObject; | |
const user = userResponse.resultObject; | |
const roles = rolesResponse.resultObjects; | |
const userRoles = userRolesResponse.resultObjects; | |
if (roles == null || userRoles == null) { | |
return new IdentityRecord({ user }); | |
} | |
const userLoginWithRole = updatedUserLogin | |
?.withRole(roles) | |
.withUserRole(userRoles); | |
const identityRecord = new IdentityRecord({ | |
role: userLoginWithRole.role, | |
user, | |
}); | |
return identityRecord; | |
}; | |
if (userLogin == null) { | |
return; | |
} | |
return getIdentity(userLogin); | |
}, | |
[getUserApi, getUserLoginApi, listRolesApi, listUserRolesApi] | |
); | |
return { buildCurrentLogin: buildCurrentIdentity }; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---------------------------------------------------- | |
// First pass refactoring breaking out small functions | |
// that are single purpose in an effort to reduce | |
// duplication and hopefully extract out of the hooks | |
// scope and perhaps out of the file all together. | |
// ---------------------------------------------------- | |
import IdentityRecord from "models/view-models/identity-record"; | |
import { useCallback } from "react"; | |
import UserLoginRecord from "models/view-models/user-login-record"; | |
import RoleService from "utilities/services/role-service"; | |
import UserService from "utilities/services/user-service"; | |
import UserRecord from "models/view-models/user-record"; | |
import RoleRecord from "models/view-models/role-record"; | |
/** | |
* Custom hook providing utility functions for the current identity of the user | |
*/ | |
export default function useIdentity() { | |
const { get: getRoleApi } = RoleService.useGet(); | |
const { get: getUserApi } = UserService.useGet(); | |
/** | |
* Build the identity record including the current User and Role | |
* | |
* @param {UserLoginRecord|undefined} (userLogin | |
* @returns Promise | |
*/ | |
const getHook = (userLogin: UserLoginRecord | undefined) => { | |
if (userLogin == null) { | |
return; | |
} | |
return getIdentity(userLogin); | |
}; | |
const getIdentity = async ( | |
userLogin: UserLoginRecord | |
): Promise<IdentityRecord | undefined> => { | |
const user = await getUser(userLogin?.userId); | |
if (user == null) { | |
return; | |
} | |
const role = await getRole(userLogin?.roleId); | |
return new IdentityRecord({ role, user }); | |
}; | |
const getRole = async ( | |
roleId: number | undefined | |
): Promise<RoleRecord | undefined> => { | |
if (roleId == null) { | |
return; | |
} | |
return (await getRoleApi({ id: roleId })).result?.resultObject; | |
}; | |
const getUser = async ( | |
userId: number | undefined | |
): Promise<UserRecord | undefined> => { | |
if (userId == null) { | |
return; | |
} | |
return (await getUserApi({ id: userId })).result?.resultObject; | |
}; | |
return { getIdentity: useCallback(getHook, [getRoleApi, getUserApi]) }; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---------------------------------------------------- | |
// Second pass refactoring extracting functions out | |
// of the scope of the hook and into form that could | |
// easily be pulled into shared utiltiies | |
// ---------------------------------------------------- | |
import IdentityRecord from "models/view-models/identity-record"; | |
import { useCallback } from "react"; | |
import UserLoginRecord from "models/view-models/user-login-record"; | |
import RoleService from "utilities/services/role-service"; | |
import UserService from "utilities/services/user-service"; | |
import { ServiceResponse } from "andculturecode-javascript-core"; | |
/** | |
* Loads and constructs data comprising an Identity record | |
*/ | |
export default function useIdentity() { | |
const { get: getRoleApi } = RoleService.useGet(); | |
const { get: getUserApi } = UserService.useGet(); | |
/** | |
* Build the identity record including the current User and Role | |
* | |
* @param {UserLoginRecord|undefined} userLogin | |
* @returns Promise | |
*/ | |
const getIdentity = async ( | |
userLogin: UserLoginRecord | |
): Promise<IdentityRecord | undefined> => { | |
const user = await _call(getUserApi, userLogin.userId); | |
if (user == null) { | |
return; | |
} | |
const role = await _call(getRoleApi, userLogin.roleId); | |
return new IdentityRecord({ role, user }); | |
}; | |
/** | |
* Hook function (a constructor of sorts, but for hooks) | |
* @param userLogin user login for which to construct the identity | |
*/ | |
const hook = (userLogin: UserLoginRecord | undefined) => | |
userLogin != null ? getIdentity(userLogin) : null; | |
return { getIdentity: useCallback(hook, [getRoleApi, getUserApi]) }; | |
} | |
// ----------------------------------------------------------------------------------------- | |
// #region Private Functions | |
// ----------------------------------------------------------------------------------------- | |
type CallbackOptions = { | |
id: number; | |
}; | |
/** | |
* Calls the provided callback if the id is set | |
* @param id id value to attempt to load | |
* @param callback | |
*/ | |
const _call = async <T>( | |
callback: (options: CallbackOptions) => Promise<ServiceResponse<T>>, | |
id: number | undefined | |
): Promise<T | undefined> => { | |
if (id == null || id < 1) { | |
return; | |
} | |
return (await callback({ id })).result?.resultObject; | |
}; | |
// #endregion Private Functions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment