DEV Community

Cover image for React.js ~Migrating Away from useEffect + setState~
Ogasawara Kakeru
Ogasawara Kakeru

Posted on

React.js ~Migrating Away from useEffect + setState~

If you have an existing codebase full of useEffect-fetch-setState pattern, you don't need to rewrite everything at once. Here is a practical migration path:

**Step 1: Extract to a Custom Hook
Before changing the data fetching mechanism, encapsulate the exisiting pattern:

function useUser(id: string) {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    let cancelled = false;
    setIsLoading(true);
    fetchUser(id)
      .then((data) => {
        if (!cancelled) setUser(data);
      })
      .catch((err) => {
        if (!cancelled) setError(err);
      })
      .finally(() => {
        if (!cancelled) setIsLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [id]);

  return { user, isLoading, error };
}
Enter fullscreen mode Exit fullscreen mode

**Step 2: Add Suspense Boundaries
Wrap the consuming components in Suspense and Error Boundaries. This is safe even before switching to use(): the boundaries just don't trigger yet:

<ErrorBoundary fallback={<ErrorMessage />}>
  <Suspense fallback={<Skeleton />}>
    <UserProfile userId={userId} />
  </Suspense>
</ErrorBoundary>
Enter fullscreen mode Exit fullscreen mode

**Step 3:Swap the Internals
Now change the custom hook(or the component) to accept a promise and use use(). The consuming components don't change; they already have Suspense boundaries:

function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
  const user = use(userPromise);
  return <ProfileCard user={user} />;
}
Enter fullscreen mode Exit fullscreen mode

**Step 4:Move the Fetch Up
Push promise creation to Server Components or to a caching layer. This is the real architectural shift, data initiation moves from the component that needs it to the component(or server) that can create a stable reference.

Top comments (0)