aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-10-30 11:18:11 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:15:27 +0100
commit84a679b0e48ed76eee2fa44d3caac83591aa3c8c (patch)
tree1d418a6c514ff8a04b84ba35c98736e8450f968c /src/utils
parent60c49f18389ff625177a57277ef8f292a31097bf (diff)
feat(hooks): add useBoolean and useToggle hooks
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/hooks/index.ts2
-rw-r--r--src/utils/hooks/use-boolean/index.ts1
-rw-r--r--src/utils/hooks/use-boolean/use-boolean.test.ts45
-rw-r--r--src/utils/hooks/use-boolean/use-boolean.ts44
-rw-r--r--src/utils/hooks/use-toggle/index.ts1
-rw-r--r--src/utils/hooks/use-toggle/use-toggle.test.ts24
-rw-r--r--src/utils/hooks/use-toggle/use-toggle.ts15
7 files changed, 132 insertions, 0 deletions
diff --git a/src/utils/hooks/index.ts b/src/utils/hooks/index.ts
index f1bb31e..b98be04 100644
--- a/src/utils/hooks/index.ts
+++ b/src/utils/hooks/index.ts
@@ -1,5 +1,6 @@
export * from './use-ackee';
export * from './use-article';
+export * from './use-boolean';
export * from './use-breadcrumb';
export * from './use-comments';
export * from './use-data-from-api';
@@ -23,3 +24,4 @@ export * from './use-settings';
export * from './use-state-change';
export * from './use-system-color-scheme';
export * from './use-theme';
+export * from './use-toggle';
diff --git a/src/utils/hooks/use-boolean/index.ts b/src/utils/hooks/use-boolean/index.ts
new file mode 100644
index 0000000..a210294
--- /dev/null
+++ b/src/utils/hooks/use-boolean/index.ts
@@ -0,0 +1 @@
+export * from './use-boolean';
diff --git a/src/utils/hooks/use-boolean/use-boolean.test.ts b/src/utils/hooks/use-boolean/use-boolean.test.ts
new file mode 100644
index 0000000..22d3cdc
--- /dev/null
+++ b/src/utils/hooks/use-boolean/use-boolean.test.ts
@@ -0,0 +1,45 @@
+import { describe, expect, it } from '@jest/globals';
+import { act, renderHook } from '@testing-library/react';
+import { useBoolean } from './use-boolean';
+
+describe('use-boolean', () => {
+ it('returns the initial state', () => {
+ const initialState = true;
+ const { result } = renderHook(() => useBoolean(initialState));
+
+ expect(result.current.state).toBe(initialState);
+ });
+
+ it('can set the state to false', () => {
+ const { result } = renderHook(() => useBoolean());
+
+ act(() => {
+ result.current.deactivate();
+ });
+
+ expect(result.current.state).toBe(false);
+ });
+
+ it('can set the state to true', () => {
+ const { result } = renderHook(() => useBoolean());
+
+ act(() => {
+ result.current.activate();
+ });
+
+ expect(result.current.state).toBe(true);
+ });
+
+ it('can switch the state', () => {
+ const initialState = true;
+ const { result } = renderHook(() => useBoolean(initialState));
+
+ expect(result.current.state).toBe(initialState);
+
+ act(() => {
+ result.current.toggle();
+ });
+
+ expect(result.current.state).toBe(!initialState);
+ });
+});
diff --git a/src/utils/hooks/use-boolean/use-boolean.ts b/src/utils/hooks/use-boolean/use-boolean.ts
new file mode 100644
index 0000000..35cb00c
--- /dev/null
+++ b/src/utils/hooks/use-boolean/use-boolean.ts
@@ -0,0 +1,44 @@
+import { useCallback, useState } from 'react';
+
+export type UseBooleanReturn = {
+ /**
+ * Set state as true.
+ */
+ activate: () => void;
+ /**
+ * Set state as false.
+ */
+ deactivate: () => void;
+ /**
+ * Current state.
+ */
+ state: boolean;
+ /**
+ * Switch state.
+ */
+ toggle: () => void;
+};
+
+/**
+ * React hook to deal with boolean states.
+ *
+ * @param {boolean} [initialState] - The initial state.
+ * @returns {UseBooleanReturn} The state and utility functions to update it.
+ */
+export const useBoolean = (initialState = false): UseBooleanReturn => {
+ const [state, setState] = useState(initialState);
+
+ const activate = useCallback(() => {
+ setState(true);
+ }, []);
+
+ const deactivate = useCallback(() => {
+ setState(false);
+ }, []);
+
+ const toggle = useCallback(() => {
+ setState((prevState) => !prevState);
+ }, []);
+
+ return { activate, deactivate, state, toggle };
+};
diff --git a/src/utils/hooks/use-toggle/index.ts b/src/utils/hooks/use-toggle/index.ts
new file mode 100644
index 0000000..01a0e57
--- /dev/null
+++ b/src/utils/hooks/use-toggle/index.ts
@@ -0,0 +1 @@
+export * from './use-toggle';
diff --git a/src/utils/hooks/use-toggle/use-toggle.test.ts b/src/utils/hooks/use-toggle/use-toggle.test.ts
new file mode 100644
index 0000000..b2feeab
--- /dev/null
+++ b/src/utils/hooks/use-toggle/use-toggle.test.ts
@@ -0,0 +1,24 @@
+import { describe, expect, it } from '@jest/globals';
+import { act, renderHook } from '@testing-library/react';
+import { useToggle } from './use-toggle';
+
+describe('use-toggle', () => {
+ it('returns the default state', () => {
+ const { result } = renderHook(() => useToggle());
+
+ expect(result.current[0]).toBe(false);
+ });
+
+ it('can switch the state', () => {
+ const initialState = true;
+ const { result } = renderHook(() => useToggle(initialState));
+
+ expect(result.current[0]).toBe(initialState);
+
+ act(() => {
+ result.current[1]();
+ });
+
+ expect(result.current[0]).toBe(!initialState);
+ });
+});
diff --git a/src/utils/hooks/use-toggle/use-toggle.ts b/src/utils/hooks/use-toggle/use-toggle.ts
new file mode 100644
index 0000000..c07c1e2
--- /dev/null
+++ b/src/utils/hooks/use-toggle/use-toggle.ts
@@ -0,0 +1,15 @@
+import { useBoolean } from '../use-boolean';
+
+export type UseToggleReturn = readonly [boolean, () => void];
+
+/**
+ * React hook to toggle boolean states.
+ *
+ * @param {boolean} [initialState] - The initial state.
+ * @returns {UseToggleReturn} The state and a function to switch state.
+ */
+export const useToggle = (initialState = false): UseToggleReturn => {
+ const { state, toggle } = useBoolean(initialState);
+
+ return [state, toggle] as const;
+};