File tree Expand file tree Collapse file tree 4 files changed +79
-11
lines changed Expand file tree Collapse file tree 4 files changed +79
-11
lines changed Original file line number Diff line number Diff line change 1+ import { DependencyList , useRef } from 'react'
2+ import useStableMemo from './useStableMemo'
3+
4+ /**
5+ * An _immediate_ effect that runs an effect callback when its dependency array
6+ * changes. This is helpful for updates should must run during render, most
7+ * commonly state derived from props; a more ergonomic version of https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops
8+ *
9+ * ```ts
10+ * function Example({ value }) {
11+ * const [intermediaryValue, setValue] = useState(value);
12+ *
13+ * useImmediateUpdateEffect(() => {
14+ * setValue(value)
15+ * }, [value])
16+ * ```
17+ */
18+ function useImmediateUpdateEffect ( effect : ( ) => void , deps : DependencyList ) {
19+ const firstRef = useRef ( true )
20+
21+ useStableMemo ( ( ) => {
22+ if ( firstRef . current ) {
23+ firstRef . current = false
24+ return
25+ }
26+
27+ effect ( )
28+ } , deps )
29+ }
30+
31+ export default useImmediateUpdateEffect
Original file line number Diff line number Diff line change 1+ import { ReactWrapper , mount } from 'enzyme'
2+ import React from 'react'
3+
4+ export function renderHook < T extends ( props : P ) => any , P = any > (
5+ fn : T ,
6+ initialProps ?: P ,
7+ ) : [ ReturnType < T > , ReactWrapper < P > ] {
8+ const result = Array ( 2 ) as any
9+
10+ function Wrapper ( props : any ) {
11+ result [ 0 ] = fn ( props )
12+ return < span />
13+ }
14+
15+ result [ 1 ] = mount ( < Wrapper { ...initialProps } /> )
16+
17+ return result
18+ }
Original file line number Diff line number Diff line change 1- import React , { useEffect } from 'react'
21import { act } from 'react-dom/test-utils'
3-
4- import { mount } from 'enzyme'
5-
62import useForceUpdate from '../src/useForceUpdate'
3+ import { renderHook } from './helpers'
74
85describe ( 'useForceUpdate' , ( ) => {
96 it ( 'should return a function that returns mount state' , ( ) => {
10- let forceUpdate : ReturnType < typeof useForceUpdate >
117 let count = 0
12- function Wrapper ( ) {
13- forceUpdate = useForceUpdate ( )
14- count ++
15- return < span />
16- }
178
18- mount ( < Wrapper /> )
9+ const [ forceUpdate ] = renderHook ( ( ) => {
10+ count ++
11+ return useForceUpdate ( )
12+ } )
1913
2014 expect ( count ) . toEqual ( 1 )
2115 act ( ( ) => {
Original file line number Diff line number Diff line change 1+ import useImmediateUpdateEffect from '../src/useImmediateUpdateEffect'
2+ import { renderHook } from './helpers'
3+
4+ describe ( 'useImmediateUpdateEffect' , ( ) => {
5+ it ( 'should return a function that returns mount state' , ( ) => {
6+ const spy = jest . fn ( )
7+
8+ const [ , wrapper ] = renderHook (
9+ ( { value } ) => {
10+ useImmediateUpdateEffect ( spy , [ value ] )
11+ } ,
12+ { value : 1 , other : false } ,
13+ )
14+
15+ expect ( spy ) . not . toHaveBeenCalled ( )
16+
17+ wrapper . setProps ( { value : 2 } )
18+
19+ expect ( spy ) . toHaveBeenCalledTimes ( 1 )
20+
21+ wrapper . setProps ( { value : 2 , other : true } )
22+
23+ expect ( spy ) . toHaveBeenCalledTimes ( 1 )
24+ } )
25+ } )
You can’t perform that action at this time.
0 commit comments