Skip to content

Commit

Permalink
Merge pull request #60 from juliencrn/feature/add-lifecycle-hooks
Browse files Browse the repository at this point in the history
feat(hooks): Create lifecycles hooks
  • Loading branch information
juliencrn authored Nov 10, 2021
2 parents 763e90b + 4341c1e commit 8412dd2
Show file tree
Hide file tree
Showing 25 changed files with 1,809 additions and 43 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ If you'd like to submit new post ideas, improve existing posts, or change anythi
- [`useCounter()`](https://usehooks-ts.com/react-hook/use-counter)
- [`useDarkMode()`](https://usehooks-ts.com/react-hook/use-dark-mode)
- [`useDebounce()`](https://usehooks-ts.com/react-hook/use-debounce)
- [`useEffectOnce()`](https://usehooks-ts.com/react-hook/use-effect-once)
- [`useElementSize()`](https://usehooks-ts.com/react-hook/use-element-size)
- [`useEventListener()`](https://usehooks-ts.com/react-hook/use-event-listener)
- [`useFetch()`](https://usehooks-ts.com/react-hook/use-fetch)
Expand All @@ -62,6 +63,7 @@ If you'd like to submit new post ideas, improve existing posts, or change anythi
- [`useIntersectionObserver()`](https://usehooks-ts.com/react-hook/use-intersection-observer)
- [`useInterval()`](https://usehooks-ts.com/react-hook/use-interval)
- [`useIsClient()`](https://usehooks-ts.com/react-hook/use-is-client)
- [`useIsFirstRender()`](https://usehooks-ts.com/react-hook/use-is-first-render)
- [`useIsMounted()`](https://usehooks-ts.com/react-hook/use-is-mounted)
- [`useLocalStorage()`](https://usehooks-ts.com/react-hook/use-local-storage)
- [`useLockedBody()`](https://usehooks-ts.com/react-hook/use-locked-body)
Expand All @@ -73,6 +75,7 @@ If you'd like to submit new post ideas, improve existing posts, or change anythi
- [`useSsr()`](https://usehooks-ts.com/react-hook/use-ssr)
- [`useStep()`](https://usehooks-ts.com/react-hook/use-step)
- [`useTimeout()`](https://usehooks-ts.com/react-hook/use-timeout)
- [`useUpdateEffect()`](https://usehooks-ts.com/react-hook/use-update-effect)
- [`useWindowSize()`](https://usehooks-ts.com/react-hook/use-window-size)

<!-- HOOKS:END -->
Expand Down
3 changes: 3 additions & 0 deletions lib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ npm i usehooks-ts
- [`useCounter()`](https://usehooks-ts.com/react-hook/use-counter)
- [`useDarkMode()`](https://usehooks-ts.com/react-hook/use-dark-mode)
- [`useDebounce()`](https://usehooks-ts.com/react-hook/use-debounce)
- [`useEffectOnce()`](https://usehooks-ts.com/react-hook/use-effect-once)
- [`useElementSize()`](https://usehooks-ts.com/react-hook/use-element-size)
- [`useEventListener()`](https://usehooks-ts.com/react-hook/use-event-listener)
- [`useFetch()`](https://usehooks-ts.com/react-hook/use-fetch)
Expand All @@ -29,6 +30,7 @@ npm i usehooks-ts
- [`useIntersectionObserver()`](https://usehooks-ts.com/react-hook/use-intersection-observer)
- [`useInterval()`](https://usehooks-ts.com/react-hook/use-interval)
- [`useIsClient()`](https://usehooks-ts.com/react-hook/use-is-client)
- [`useIsFirstRender()`](https://usehooks-ts.com/react-hook/use-is-first-render)
- [`useIsMounted()`](https://usehooks-ts.com/react-hook/use-is-mounted)
- [`useLocalStorage()`](https://usehooks-ts.com/react-hook/use-local-storage)
- [`useLockedBody()`](https://usehooks-ts.com/react-hook/use-locked-body)
Expand All @@ -40,6 +42,7 @@ npm i usehooks-ts
- [`useSsr()`](https://usehooks-ts.com/react-hook/use-ssr)
- [`useStep()`](https://usehooks-ts.com/react-hook/use-step)
- [`useTimeout()`](https://usehooks-ts.com/react-hook/use-timeout)
- [`useUpdateEffect()`](https://usehooks-ts.com/react-hook/use-update-effect)
- [`useWindowSize()`](https://usehooks-ts.com/react-hook/use-window-size)

<!-- HOOKS:END -->
Expand Down
3 changes: 3 additions & 0 deletions lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './useCopyToClipboard'
export * from './useCounter'
export * from './useDarkMode'
export * from './useDebounce'
export * from './useEffectOnce'
export * from './useElementSize'
export * from './useEventListener'
export * from './useFetch'
Expand All @@ -11,6 +12,7 @@ export * from './useImageOnLoad'
export * from './useIntersectionObserver'
export * from './useInterval'
export * from './useIsClient'
export * from './useIsFirstRender'
export * from './useIsMounted'
export * from './useLocalStorage'
export * from './useLockedBody'
Expand All @@ -22,4 +24,5 @@ export * from './useScript'
export * from './useSsr'
export * from './useStep'
export * from './useTimeout'
export * from './useUpdateEffect'
export * from './useWindowSize'
2 changes: 2 additions & 0 deletions lib/src/useEffectOnce/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as useEffectOnce } from './useEffectOnce'
export * from './useEffectOnce'
16 changes: 16 additions & 0 deletions lib/src/useEffectOnce/useEffectOnce.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { renderHook } from '@testing-library/react-hooks/native'

import useEffectOnce from './useEffectOnce'

describe('use effect once()', () => {
test('should be triggered only once', () => {
const effect = jest.fn()
const { rerender } = renderHook(() => useEffectOnce(effect))

expect(effect).toHaveBeenCalledTimes(1)

rerender()

expect(effect).toHaveBeenCalledTimes(1)
})
})
8 changes: 8 additions & 0 deletions lib/src/useEffectOnce/useEffectOnce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { EffectCallback, useEffect } from 'react'

function useEffectOnce(effect: EffectCallback) {
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(effect, [])
}

export default useEffectOnce
2 changes: 2 additions & 0 deletions lib/src/useIsFirstRender/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as useIsFirstRender } from './useIsFirstRender'
export * from './useIsFirstRender'
15 changes: 15 additions & 0 deletions lib/src/useIsFirstRender/useIsFirstRender.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { renderHook } from '@testing-library/react-hooks/native'

import useIsFirstRender from './useIsFirstRender'

describe('use is first render()', () => {
test('should return true at the first render, next false', () => {
const { result, rerender } = renderHook(() => useIsFirstRender())

expect(result.current).toBe(true)

rerender()

expect(result.current).toBe(false)
})
})
15 changes: 15 additions & 0 deletions lib/src/useIsFirstRender/useIsFirstRender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useRef } from 'react'

function useIsFirstRender(): boolean {
const isFirst = useRef(true)

if (isFirst.current) {
isFirst.current = false

return true
}

return isFirst.current
}

export default useIsFirstRender
2 changes: 2 additions & 0 deletions lib/src/useUpdateEffect/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as useUpdateEffect } from './useUpdateEffect'
export * from './useUpdateEffect'
16 changes: 16 additions & 0 deletions lib/src/useUpdateEffect/useUpdateEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { renderHook } from '@testing-library/react-hooks/native'

import useUpdateEffect from './useUpdateEffect'

describe('use update effect()', () => {
test('the callback function should have been called on update', () => {
const effect = jest.fn()
const { rerender } = renderHook(() => useUpdateEffect(effect))

expect(effect).not.toHaveBeenCalled()

rerender()

expect(effect).toHaveBeenCalledTimes(1)
})
})
16 changes: 16 additions & 0 deletions lib/src/useUpdateEffect/useUpdateEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { DependencyList, EffectCallback, useEffect } from 'react'

import { useIsFirstRender } from '../useIsFirstRender'

function useUpdateEffect(effect: EffectCallback, deps?: DependencyList) {
const isFirst = useIsFirstRender()

useEffect(() => {
if (!isFirst) {
return effect()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps)
}

export default useUpdateEffect
Loading

0 comments on commit 8412dd2

Please sign in to comment.