Last active
July 19, 2025 18:10
-
-
Save krivaten/2b71c39e15bd748ba6b6e86de0c68ab2 to your computer and use it in GitHub Desktop.
Better State Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An enum representing the possible states of UI features | |
* | |
* These states help design consistent user experiences across different | |
* scenarios like loading, empty states, errors, and varying data quantities. | |
*/ | |
export enum State { | |
/** | |
* The starting state before any user interaction or data loading. | |
* Example: A search page before the user has entered a query. | |
*/ | |
INITIAL = "INITIAL", | |
/** | |
* An asynchronous operation is in progress (loading, saving, etc.). | |
* Example: Showing a spinner while fetching search results. | |
*/ | |
PENDING = "PENDING", | |
/** | |
* An asynchronous operation has completed successfully. | |
* Note: This typically transitions to NONE, ONE, SOME, or MANY based on results. | |
*/ | |
DONE = "DONE", | |
/** | |
* No data/items are available to display. | |
* Example: "No search results found" or empty shopping cart. | |
*/ | |
NONE = "NONE", | |
/** | |
* Exactly one item is present. | |
* Example: Single search result or one item in cart. | |
*/ | |
ONE = "ONE", | |
/** | |
* A small number of items are present (typically 2-10). | |
* UI consideration: Simple list layout, no pagination needed. | |
*/ | |
SOME = "SOME", | |
/** | |
* A large number of items are present (typically 10+). | |
* UI consideration: Requires pagination, virtualization, or load-more patterns. | |
*/ | |
MANY = "MANY", | |
/** | |
* An error has occurred (validation, network, server, etc.). | |
* Example: Form validation errors, failed API requests. | |
*/ | |
ERROR = "ERROR", | |
/** | |
* An operation completed successfully with user feedback needed. | |
* Example: "Profile saved successfully" confirmation message. | |
*/ | |
SUCCESS = "SUCCESS", | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
useEffect(() => { | |
(async () => { | |
try { | |
const { profiles } = await apiRequest(`/profiles`); | |
setProfiles(profiles); | |
const profilesCount = profiles.length || 0; | |
if (profilesCount === 0) | |
setState(State.NONE); | |
else if (profilesCount === 1) | |
setState(State.ONE); | |
else if (profilesCount > 1 && profilesCount <= 5) | |
setState(State.SOME); | |
else | |
setState(State.MANY); | |
} catch (error) { | |
setState(State.ERROR); | |
console.error("Failed to fetch profiles:", error); | |
} | |
})(); | |
}, []); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div> | |
<PageSubtitle>Profile</PageSubtitle> | |
{state === State.LOADING && <Spinner />} | |
{state === State.NONE && ( | |
<> | |
<Alert> | |
<Info className="h-4 w-4" /> | |
<AlertTitle>No profiles</AlertTitle> | |
<AlertDescription> | |
You don't have any profiles. Let's create one! | |
</AlertDescription> | |
</Alert> | |
<ProfileForm /> | |
</> | |
)} | |
{state === State.ONE && ( | |
<> | |
<ProfileForm profile={profiles[0]} /> | |
<Button onClick={this.createNewProfile}> | |
Create New Profile | |
</Button> | |
</> | |
)} | |
{(state === State.SOME || state === State.MANY) && ( | |
<ul className="divide-y divide-gray-100"> | |
{profiles.map((profile) => ( | |
<li key={profile?.id}> | |
<div className="font-semibold"> | |
{profile.first_name} {profile.last_name} | |
{profile.display_name | |
? ` (${profile.display_name})` | |
: undefined} | |
</div> | |
<div className="text-xs"> | |
{profile.created_at | |
? new Date(profile.created_at).toDateString() | |
: undefined} | |
</div> | |
</li> | |
))} | |
</ul> | |
)} | |
{state === State.ERROR && ( | |
<> | |
<Alert> | |
<Info className="h-4 w-4" /> | |
<AlertTitle>Error</AlertTitle> | |
<AlertDescription> | |
There was an issue fetching your profiles. Please try again. | |
</AlertDescription> | |
</Alert> | |
</> | |
)} | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment