diff --git a/packages/vue/src/composables/useMounted/index.test.ts b/packages/vue/src/composables/useMounted/index.test.ts
new file mode 100644
index 0000000..da2adb0
--- /dev/null
+++ b/packages/vue/src/composables/useMounted/index.test.ts
@@ -0,0 +1,27 @@
+import { describe, expect, it } from 'vitest';
+import { defineComponent, nextTick, ref } from 'vue';
+import { mount } from '@vue/test-utils'
+import { useMounted } from '.';
+
+const ComponentStub = defineComponent({
+ setup() {
+ const isMounted = useMounted();
+
+ return { isMounted };
+ },
+ template: `
{{ isMounted }}
`,
+});
+
+describe('useMounted', () => {
+ it('return the mounted state of the component', async () => {
+ const component = mount(ComponentStub);
+
+ // Initial render
+ expect(component.text()).toBe('false');
+
+ await nextTick();
+
+ // Will trigger a render
+ expect(component.text()).toBe('true');
+ });
+});
diff --git a/packages/vue/src/composables/useMounted/index.ts b/packages/vue/src/composables/useMounted/index.ts
new file mode 100644
index 0000000..16ea4f5
--- /dev/null
+++ b/packages/vue/src/composables/useMounted/index.ts
@@ -0,0 +1,25 @@
+import { onMounted, readonly, ref, type ComponentInternalInstance } from 'vue';
+import { getLifeCycleTarger } from '../../utils';
+
+/**
+ * @name useMounted
+ * @category Components
+ * @description Returns a ref that tracks the mounted state of the component (doesn't track the unmounted state)
+ *
+ * @param {ComponentInternalInstance} [instance] The component instance to track the mounted state for
+ * @returns {Readonly[>} The mounted state of the component
+ *
+ * @example
+ * const isMounted = useMounted();
+ *
+ * @example
+ * const isMounted = useMounted(getCurrentInstance());
+ */
+export function useMounted(instance?: ComponentInternalInstance) {
+ const isMounted = ref(false);
+ const targetInstance = getLifeCycleTarger(instance);
+
+ onMounted(() => isMounted.value = true, targetInstance);
+
+ return readonly(isMounted);
+}
]