Skip to content

Commit 437c417

Browse files
committed
fix(useIsInitialRenderRef): clarify usage and fix ordering
1 parent 427cef8 commit 437c417

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

src/useIsInitialRenderRef.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,26 @@ import { useEffect, useLayoutEffect, useRef } from 'react'
22

33
/**
44
* Returns ref that is `true` on the initial render and `false` on subsequent renders. It
5-
* is StrictMode safe, so will reset correctly if the component is unmounted and remounted
5+
* is StrictMode safe, so will reset correctly if the component is unmounted and remounted.
6+
*
7+
* This hook *must* be used before any effects that read it's value to be accurate.
68
*/
79
export default function useIsInitialRenderRef() {
10+
const effectCount = useRef(0)
811
const isInitialRenderRef = useRef(true)
912

1013
useLayoutEffect(() => {
11-
isInitialRenderRef.current = false
14+
effectCount.current += 1
15+
16+
if (effectCount.current >= 2) {
17+
isInitialRenderRef.current = false
18+
}
1219
})
1320

1421
// Strict mode handling in React 18
1522
useEffect(
1623
() => () => {
24+
effectCount.current = 0
1725
isInitialRenderRef.current = true
1826
},
1927
[],

test/helpers.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { renderHook as baseRenderHook } from '@testing-library/react-hooks'
2-
import React from 'react'
32

43
type ReactWrapper<P> = {
54
setProps(props: Partial<P>): void

test/useIsInitialRenderRef.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { act, renderHook } from '@testing-library/react-hooks'
2+
import useIsInitialRenderRef from '../src/useIsInitialRenderRef'
3+
import { useLayoutEffect } from 'react'
4+
5+
describe('useIsInitialRenderRef', () => {
6+
it('should not be true until the second committed render', () => {
7+
let count = 0
8+
9+
// TODO: test with strict mode
10+
const { rerender } = renderHook(() => {
11+
const ref = useIsInitialRenderRef()
12+
13+
useLayoutEffect(() => {
14+
if (ref.current) return
15+
16+
count++
17+
})
18+
})
19+
20+
expect(count).toEqual(0)
21+
22+
rerender()
23+
24+
expect(count).toEqual(1)
25+
})
26+
})

0 commit comments

Comments
 (0)