DEV Community

quyet
quyet

Posted on

Better way to handle visibility states on UI

When building user interfaces, it's often necessary to manage toggle states for different components. Toggles can represent various UI elements, such as modals or loading indicators, that can be either visible or hidden.

Traditionally, booleans have been used to manage toggle states in UI components. For example, a boolean value can be used to indicate whether a modal is visible or hidden. However, using a boolean value can have limitations, especially when dealing with more complex components that have multiple toggle states.

In this blog post, we'll explore how using strings can provide more flexibility and control over toggle UI state. We'll look at an example of a parent component that contains visibility state of multiple modals (delete/edit/new) and loading statuses using boolean and using string at the same time.

Using Booleans for Toggle UI State

Let's consider a scenario where we have a parent component that manages the visibility state of three modals - delete, edit, and new. We can use a boolean value for each modal to indicate whether it's currently visible or hidden.

Here's an example code snippet:

<script setup lang="ts">
import { ref, onMounted } from "vue"
type Member = {
    id: number
    name: string
}
const isLoading = ref(false)
const isDeleteModalVisible = ref(false)
const isEditModalVisible = ref(false)
const isNewModalVisible = ref(false)
const members = ref<Member[]>([])
const selectedMember = ref<Member | null>(null)

function onMemberSelected(member: Member) {
    selectedMember.value = member
}

onMounted(async () => {
    isLoading.value = true
    members.value = await fetchMembers()
    isLoading.value = false
})
</script>
<template>
    <Spinner v-if="isLoading" />
    <div v-else>
        <MemberList :members="members" @member-selected="onMemberSelected" />
        <button @click="isDeleteModalVisible = true">Delete</button>
        <button @click="isEditModalVisible = true">Edit</button>
        <button @click="isNewModalVisible = true">New</button>
        <DeleteModal :visible="isDeleteModalVisible" @done="isDeleteModalVisible = false" />
        <EditModal :visible="isEditModalVisible" @done="isEditModalVisible = false" />
        <NewModal :visible="isNewModalVisible" @done="isNewModalVisible = false" />
    </div>
</template>

Enter fullscreen mode Exit fullscreen mode

While this approach works for simple components with just a few toggle states, it can become unwieldy for more complex components that have multiple possible toggle states.

Using Strings for Toggle UI State

Now, let's consider the same scenario but using strings instead of booleans to manage the toggle UI state. Instead of a boolean value, we can use a string value to represent the current state of each modal.

Here's an example code snippet:

<script setup lang="ts">
import { ref, onMounted } from "vue"
type Member = {
    id: number
    name: string
}
enum UIState {
    idle = "idle",
    loading = "loading",
    showingDeleteModal = "showingDeleteModal",
    showingEditModal = "showingEditModal",
    showingNewModal = "showingNewModal",
}
const uiState = ref<UIState>(UIState.loading)
const members = ref<Member[]>([])
const selectedMember = ref<Member | null>(null)

function onMemberSelected(member: Member) {
    selectedMember.value = member
}

onMounted(async () => {
    uiState.value = UIState.loading
    members.value = await fetchMembers()
    uiState.value = UIState.idle
})
</script>
<template>
    <Spinner v-if="uiState === UIState.loading" />
    <div v-else>
        <MemberList :members="members" @member-selected="onMemberSelected" />
        <button @click="uiState = UIState.showingDeleteModal">Delete</button>
        <button @click="uiState = UIState.showingEditModal">Edit</button>
        <button @click="uiState = UIState.showingNewModal">New</button>
        <DeleteModal :visible="uiState === UIState.showingDeleteModal" @done="uiState = UIState.idle" />
        <EditModal :visible="uiState === UIState.showingEditModal" @done="uiState = UIState.idle" />
        <NewModal :visible="uiState === UIState.showingNewModal" @done="uiState = UIState.idle" />
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

It's worth to note that using Boolean state to handle visibility states together might lead to unexpected state (edit modal and delete modal can be true at the same time). But when using String state, this can't be happening.

Conclusion

In conclusion, while using booleans to manage toggle UI state is a common approach, using strings can provide more flexibility and control, especially when dealing with complex components that have multiple possible toggle states.

Top comments (0)