DEV Community

axtk
axtk

Posted on

Lightweight pending state handling in React

Managing loading state is very common to React apps, but most ways to track an async action's state are wired into complex libs either for data fetching (like TanStack React Query, RTK Query) or shared state management (like Redux Toolkit). Sometimes adding such a lib might feel like an overkill. So what can we go for instead?

It would be nice to handle the pending and error states of an async action without rewriting the async action, without affecting the existing app's state management, and yet with a clear way to share the action's state with multiple components, when necessary.

To address this task I created a small package called @t8/react-pending. Here's what it takes to set up an async action's state handling with this package:

+ import {usePendingState} from '@t8/react-pending';

  const ItemList = () => {
      const [items, setItems] = useState([]);
+     const [state, withState] = usePendingState('item-list');

      useEffect(() => {
-         fetchItems().then(setItems);
+         withState(fetchItems()).then(setItems);
      }, [fetchItems, withState]);

+     if (!state.complete)
+         return <p>Loading...</p>;

+     if (state.error)
+         return <p>An error occurred</p>;

      return <ul>{items.map(/* ... */)}</ul>;
  };

  const Status = () => {
+     const [state] = usePendingState('item-list');
+
+     return state.complete ? 'Done' : 'Busy';
  };
Enter fullscreen mode Exit fullscreen mode

The added code doesn't alter the original structure and the async action's code. In our example, the data is stored in local state, but it could be stored elsewhere.

The string parameter of the usePendingState() hook assigns a unique key to the particular state that can be used inside other components to refer to that state (like in Status in the example above). When the pending state is only required within a single component, we can just omit the hook's parameter.

So when introducing a complex data fetching lib feels redundant, this small single-purpose lib, can offer a neat, minimalist way to set up the async action state handling, either local or shared, without affecting the app's state.

Top comments (0)