Skip to content

Refactor: create a reusable useEffectAsync or useFetchEffect custom hook for data-loading effects #345

Description

@bg-playground

Now that #344 is merged, all data-loading useEffect effects follow this pattern:

useEffect(() => {
  let cancelled = false;
  void (async () => {
    if (!cancelled) {
      await loadData();
    }
  })();
  return () => {
    cancelled = true;
  };
}, [loadData]);

We already have hooks for forms, feature flags, and user roles, e.g.:

Let's consider extracting a custom hook like useEffectAsync/useAsyncEffect/useFetchEffect to DRY up this repeated pattern:


Possible API (naming bikeshedding allowed):

useEffectAsync(callback, deps)
  • Accepts an async callback
  • Handles cancellation logic

Example:

useEffectAsync(async () => { await loadData(); }, [loadData])
  • Optionally allow returning a teardown/cleanup function

Value:

  • Deduplicate ~10+ effect bodies project-wide
  • Less chance of forgetting cancellation
  • Clearer intent in new code

Acceptance Criteria

  • A useEffectAsync (or similar) is implemented and tested
  • All relevant useEffect calls in data-loading pages are migrated
  • No accidental double subscription/logging/cleanup regressions
  • Lint/CI still passes

Let's use this issue to bikeshed names, agree on ergonomic API, and track progress.


Related hooks for design reference:

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions