Using Custom Hooks
As one of the initial priorities in efficient development of CollegeGuide, we focused on creating custom hooks for efficient request and response handling between the frontend and backend. These include your typical GET, POST, PATCH and DELETE requests to the Django backend in order to efficiently communicate with the SQLite database. Rather than running an api.post(URL, PAYLOAD) with error and response handling, the hooks aim to manage all of this, avoiding code repetition and ensuring focus is placed on core component functionality.
We created the following:
- useGet()
- usePost()
- usePatch()
- useDelete()
- useUser()
For all custom hooks, except for useUser(), which is a special and extremely powerful hook, they are initialised in a similar way:
const {data, isLoading, error} = useGet("/posts/");
Data represents response data, isLoading is true while the request is ongoing, and error returns any errors in the process. Additionally, usePost(), usePatch() and useDelete() all return functions that can be put anywhere in the component with the custom hook called to perform their function, such as postData(url, payload) for usePost(). Once again, this offers similar functionality to api.post() without the repeating need of error checking and such.
useUser() offers a useful toolset for the currently logged in user by returning their user ID, username, email, profile details, privilege level, verified status and many more through handling the JWT session token and running some of its own fetches.
General Component Layout
With these, we have achieved a more streamlined approach for developing each component. For example:
// React Imports...
// Component Imports...
import useUser from "../custom_hooks/useUser";
import useGet from "../custom_hooks/useGet";
const Component = () => {
const { currentUserId, isLoading: userData_l, error: userData_e } = useUser();
const { data: postsData_d, isLoading: postsData_l, error: postsData_e } = useGet("/posts/");
// ...
// Component-relevant functions, hooks and states
// ...
const anyLoading = userData_l || postsData_l;
const anyError = userData_e || postsData_e;
if (anyLoading) return <div>Loading...</div>
if (anyError) return <div>Error: {anyError}</div>
return (
<div>Component Body</div>
);
}
We aim to follow the above template for all components for both convenience and clarity.