useEffectOnce()

Just modified version of useEffect that's executed only one time, at the mounting time.

See also:

The Hook

1import { EffectCallback, useEffect, useRef } from 'react'
2
3function useEffectOnce(effect: EffectCallback) {
4 // eslint-disable-next-line @typescript-eslint/no-explicit-any
5 const destroyFunc = useRef<void | any>()
6 const calledOnce = useRef(false)
7 const renderAfterCalled = useRef(false)
8
9 if (calledOnce.current) {
10 renderAfterCalled.current = true
11 }
12
13 useEffect(() => {
14 if (calledOnce.current) {
15 return
16 }
17
18 calledOnce.current = true
19 destroyFunc.current = effect()
20
21 return () => {
22 if (!renderAfterCalled.current) {
23 return
24 }
25
26 if (destroyFunc.current) {
27 destroyFunc.current()
28 }
29 }
30 // eslint-disable-next-line react-hooks/exhaustive-deps
31 }, [])
32}
33
34export default useEffectOnce

Usage

1import React, { useEffect, useState } from 'react'
2
3import { useEffectOnce } from 'usehooks-ts'
4
5export default function Component() {
6 const [data, setData] = useState<number>(0)
7 useEffect(() => {
8 console.log('Normal useEffect', { data })
9 }, [data])
10
11 useEffectOnce(() => {
12 console.log('Triggered only once, on mount', { data })
13 })
14
15 return (
16 <div>
17 <p>Open your console</p>
18 <button onClick={() => setData(Date.now())}>Update data</button>
19 </div>
20 )
21}

Edit on CodeSandbox

See a way to make this page better?
Edit there »