DEV Community

Alexander Kazanski
Alexander Kazanski

Posted on

Your Nutrition App Needs to Work in a Basement With No Signal

People log meals and workouts in gyms, on hiking trails, in hospital waiting rooms — exactly the places where connectivity is worst. If your React health app assumes a live connection to save every entry, you've built something that fails its users at the moment they most need it to work.

A minimal offline-first pattern

You don't need a full sync engine to start. A local queue plus optimistic UI gets you most of the way there:

function useOfflineQueue(syncFn) {
  const [queue, setQueue] = useState(() => {
    const saved = localStorage.getItem("pending-sync");
    return saved ? JSON.parse(saved) : [];
  });

  useEffect(() => {
    localStorage.setItem("pending-sync", JSON.stringify(queue));
  }, [queue]);

  useEffect(() => {
    if (!navigator.onLine || queue.length === 0) return;

    const flush = async () => {
      for (const item of queue) {
        try {
          await syncFn(item);
          setQueue((prev) => prev.filter((q) => q.id !== item.id));
        } catch {
          break; // stop and retry later, preserve order
        }
      }
    };
    flush();
  }, [queue, syncFn]);

  const enqueue = (item) => setQueue((prev) => [...prev, { ...item, id: crypto.randomUUID() }]);

  return { enqueue, pendingCount: queue.length };
}
Enter fullscreen mode Exit fullscreen mode

The break on failure is deliberate — retrying out of order can corrupt a meal log's timeline. It's slower to recover from a bad connection, but it protects the thing users actually care about: an accurate history.

Where teams cut corners

The tempting shortcut is to show a spinner and block the UI until the sync succeeds. Don't. The entry should appear logged immediately, with a quiet, non-alarming indicator that it's pending sync. A user who just finished a workout doesn't want to babysit a network request.

The tradeoff

Building this properly costs you real engineering time — conflict resolution, queue persistence, retry backoff. For a side project or MVP, a simpler "save and hope" approach might be the right call. But if your app markets itself around reliability for people managing real health routines, offline handling isn't a nice-to-have feature. It's the actual product.

Top comments (0)