Skip to content

Commit

Permalink
feat(hook): add new hook useToggle
Browse files Browse the repository at this point in the history
  • Loading branch information
chornos13 committed Feb 12, 2021
1 parent a8266ed commit b7857f3
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
120 changes: 120 additions & 0 deletions src/hooks/useToggle/__test__/useToggle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { renderHook, act } from '@testing-library/react-hooks'
import useToggle from 'hooks/useToggle/useToggle'

describe('basic function', () => {
test('should isToggled false for default state', () => {
// arrange
const { result } = renderHook(() => useToggle())

// assert
expect(result.current.isToggled).toEqual(false)
})

test('should set default state when passing argument configs', () => {
// arrange
const initialState = {
anyDefaultState: 'anyDefaultValue',
}
const { result } = renderHook(() =>
useToggle({
initialToggle: true,
initialState,
}),
)

// assert
expect(
result.current.isToggled === true &&
result.current.state === initialState,
).toBeTruthy()
})

test('should set isToggled true when call toggle function', () => {
// arrange
const { result } = renderHook(() => useToggle())

// act
act(() => {
result.current.toggle()
})

// assert
expect(result.current.isToggled).toEqual(true)
})

test('should set isToggled false when call untoggle function', () => {
// arrange
const { result } = renderHook(() => useToggle())

// act
act(() => {
result.current.untoggle()
})

// assert
expect(result.current.isToggled).toEqual(false)
})

test('should set state when passing argument state in toggle function', () => {
// arrange
const state = {
anyData: 'anyValue',
}
const { result } = renderHook(() => useToggle())

// act
act(() => {
result.current.toggle(state)
})

// assert
expect(result.current.state).toEqual(state)
})

test('should set state when passing argument state in untoggle function', () => {
// arrange
const state = {
anyData: 'anyValue',
}
const { result } = renderHook(() => useToggle())

// act
act(() => {
result.current.untoggle(state)
})

// assert
expect(result.current.state).toEqual(state)
})

test('should merge state when set a new state', () => {
// arrange
const initialState = {
anyInitialData: 'anyInitialValue',
}
const firstNewState = {
anyFirstData: 'anyFirstValue',
}
const newState = {
anyNewData: 'anyNewValue',
}
const { result } = renderHook(() =>
useToggle({
initialState,
}),
)

// act
act(() => {
result.current.toggle(firstNewState)
result.current.toggle(newState)
})

// assert
expect(result.current.state).toEqual({
...initialState,
...firstNewState,
...newState,
})
})
})
3 changes: 3 additions & 0 deletions src/hooks/useToggle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import useToggle from 'hooks/useToggle/useToggle'

export default useToggle
52 changes: 52 additions & 0 deletions src/hooks/useToggle/useToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useMemo, useReducer } from 'react'

interface UseToggleConfigs<T> {
initialToggle?: boolean
initialState?: T
}

const TOGGLE_ACTION_TYPE = {
TOGGLE: 'toggle',
UNTOGGLE: 'untoggle',
}

const INITIAL_COUNTER = 0

function useToggle<T>(configs?: UseToggleConfigs<T>) {
const { initialToggle = false, initialState = {} } = { ...configs }

const [data, dispatch] = useReducer(
([, prevState, counter], action) => {
const isToggled = action.type === TOGGLE_ACTION_TYPE.TOGGLE
return [isToggled, { ...prevState, ...action.state }, counter + 1]
},
[initialToggle, initialState, INITIAL_COUNTER],
)

const [isToggled, state, counter] = data

return useMemo(() => {
function setState(type: 'toggle' | 'untoggle' | string, state) {
dispatch({
type,
state,
})
}

function toggle(state?: T | any) {
setState(TOGGLE_ACTION_TYPE.TOGGLE, state)
}

function untoggle(state?: T | any) {
setState(TOGGLE_ACTION_TYPE.UNTOGGLE, state)
}
return {
isToggled,
state,
toggle,
untoggle,
}
}, [counter])
}

export default useToggle

0 comments on commit b7857f3

Please sign in to comment.