With Data Fetching

This is just a complex example to show how React Unforget can handle complex logic and data fetching.

Input Code
import React, { useState, useEffect, useMemo, useCallback } from "react";

const fetchUser = () => {
  return fetch("https://api.github.com/users/mohebifar").then((response) => {
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    return response.json();
  });
};

const fetchUserFollowers = () => {
  return fetch("https://api.github.com/users/mohebifar/followers").then(
    (response) => {
      if (!response.ok) {
        throw new Error("Network response was not ok");
      }
      return response.json();
    }
  );
};

function UserList() {
  const [user, setUser] = useState(null);
  const [followers, setFollowers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [shouldFilterUsers, setShouldFilterUsers] = useState(false);

  useEffect(() => {
    Promise.all([
      fetchUser(),
      fetchUserFollowers(),
      new Promise((resolve) => setTimeout(resolve, 2000)),
    ])
      .then(([userData, followersData]) => {
        setFollowers(followersData);
        setUser(userData);
        setLoading(false);
      })
      .catch((error) => {
        setError(error.toString());
        setLoading(false);
      });
  }, []);

  // useCallback to memoize a hypothetical handler function
  const handleUserClick = useCallback((userId) => {
    console.log("User clicked:", userId);
    // Handler logic here...
  }, []);

  // without useCallback
  const toggleEvenOnes = () => {
    setShouldFilterUsers((prev) => !prev);
  };

  const memoizedFollowers = useMemo(() => followers, [followers]);

  const filteredUsers = [];
  for (let i = 0; i < memoizedFollowers.length; i++) {
    const user = memoizedFollowers[i];
    if (i % 2 === 0) {
      filteredUsers.push(user);
    }
  }

  const usersForUI = shouldFilterUsers ? filteredUsers : memoizedFollowers;

  // Early return for loading state
  if (loading) return <div>Loading...</div>;

  // Early return for error state
  if (error) return <div>Error: {error}</div>;

  const userListElement = usersForUI.map((follower) => (
    <UserListItem key={follower.id} user={follower} />
  ));

  return (
    <div>
      <h4>Follwers of {user.name}</h4>
      <button onClick={toggleEvenOnes}>
        {shouldFilterUsers ? "Show all" : "Filter users"}
      </button>
      <ul style={{ padding: 0 }} onClick={() => handleUserClick(user.id)}>{userListElement}</ul>
    </div>
  );
}

function UserListItem({ user: { login, avatar_url, html_url } }) {
  return (
    <li
      style={{
        display: "flex",
        alignItems: "center",
        justifyContent: "space-between",
        gap: 10,
        marginBottom: 10,
      }}
    >
      <img
        style={{
          width: 100,
          height: 100,
          borderRadius: 20,
        }}
        src={avatar_url}
        alt={login}
      />
      <a href={html_url}>{login}</a>
    </li>
  );
}

export default UserList;

React Unforget Result

export default function App() {
  return <div>Compiling...</div>;
}

Read-only
Click here to view the dependency graph