useLoading
useLoading is a custom hook that tracks the loading state of an effect action in Redux. It returns true when an effect action is dispatched and resets to false when the corresponding .succeeded or .failed action is dispatched. This hook is particularly useful for managing UI loading indicators tied to asynchronous operations.
Importing
To use useLoading, import it from @blue-functor/remodel:
import { useLoading } from '@blue-functor/remodel';Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
action | Action | ActionCreator | string | Yes | The effect action to track. Accepts an action object, action creator, or action type string. The hook monitors the loading state of this action in the Redux store. |
Returns
A boolean value indicating whether the specified action is currently in a loading state. Returns false by default if the action state is not found.
Example Usage
Basic Usage: Tracking with Action Creator
import React from 'react';
import { useLoading } from '@blue-functor/remodel';
import { signIn } from '@/models/users/';
const LoadingButton: React.FC = () => {
const isLoading = useLoading(signIn);
return (
<button disabled={isLoading}>
{isLoading ? 'Signing In...' : 'Sign In'}
</button>
);
};
export default LoadingButton;In this example:
useLoadingtracks thesignInaction, which is anEffectActionCreator.- The button is disabled and displays a loading state when the action is being processed.
Using with Action Object
import React from 'react';
import { useLoading } from '@blue-functor/remodel';
import { fetchUser } from '@/models/users/';
const UserProfile: React.FC<{ userId: string }> = ({ userId }) => {
const dispatch = useDispatch();
const isLoading = useLoading(fetchUser(userId));
React.useEffect(() => {
dispatch(fetchUser(userId));
}, [userId]);
if (isLoading) return <Spinner />;
return <ProfileData />;
};Using with Action Type String
import React from 'react';
import { useLoading } from '@blue-functor/remodel';
const DataList: React.FC = () => {
const isLoading = useLoading('@/FETCH_DATA');
return (
<div>
{isLoading ? <LoadingSpinner /> : <DataTable />}
</div>
);
};Multiple Loading States
import React from 'react';
import { useLoading } from '@blue-functor/remodel';
import { fetchPosts, fetchUsers, fetchComments } from '@/models/';
const Dashboard: React.FC = () => {
const postsLoading = useLoading(fetchPosts);
const usersLoading = useLoading(fetchUsers);
const commentsLoading = useLoading(fetchComments);
const isAnyLoading = postsLoading || usersLoading || commentsLoading;
return (
<div>
{isAnyLoading && <GlobalLoadingBar />}
<PostsSection loading={postsLoading} />
<UsersSection loading={usersLoading} />
<CommentsSection loading={commentsLoading} />
</div>
);
};How It Works
-
State Subscription:
- The hook uses
useSelectorto access thestate.effect.loadingslice in the Redux store. - The
action.typeis extracted automatically whether you pass an action creator, action object, or string. - Uses safe optional chaining (
?.) to prevent errors if the action state doesn’t exist yet.
- The hook uses
-
Automatic Setup:
- The
loadingstate is managed by the system epics and system reducer, which are included out of the box with@blue-functor/remodel. - No additional setup is required. The system epics automatically track the lifecycle of effect actions and update the
loadingstate in the Redux store.
- The
-
Performance Optimization:
- The action type is memoized using
useMemoto prevent unnecessary selector recreations. - Returns
falseby default instead ofundefinedfor cleaner boolean logic.
- The action type is memoized using
Best Practices
✅ Do
// Use with action creator
const isLoading = useLoading(fetchData);
// Combine multiple loading states
const loading = useLoading(action1) || useLoading(action2);
// Use for conditional rendering
if (isLoading) return <Spinner />;❌ Don’t
// Don't create new action objects in render
const isLoading = useLoading(fetchData(id)); // Creates new object every render
// Instead, use the action creator reference
const isLoading = useLoading(fetchData);Notes
-
UI Integration: Use
useLoadingto conditionally render loading indicators, disable buttons, or show spinners based on the current state of asynchronous actions. -
Type Safety: The hook accepts flexible input types while maintaining type safety through TypeScript inference.
-
React Native Compatible: Works seamlessly in both React web and React Native applications.
useLoading provides a seamless way to integrate loading states with your UI, leveraging the built-in system reducer and epics for effortless setup.