Skip to content

Commit fa25d7d

Browse files
committed
main 🧊 rework use latest hook
1 parent 0f9a1ae commit fa25d7d

File tree

4 files changed

+44
-10
lines changed

4 files changed

+44
-10
lines changed
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
1-
import { useRef } from 'react';
1+
import { useMemo, useRef } from 'react';
22
/**
33
* @name useLatest
44
* @description - Hook that returns the stable reference of the value
55
* @category Utilities
66
*
77
* @template Value The type of the value
88
* @param {Value} value The value to get the previous value
9-
* @returns {Value} The previous value
9+
* @returns {UseLatestReturn<Value>} The previous value
1010
*
1111
* @example
1212
* const latestValue = useLatest(value);
1313
*/
1414
export const useLatest = (value) => {
1515
const valueRef = useRef(value);
1616
valueRef.current = value;
17-
return valueRef.current;
17+
return useMemo(
18+
() => ({
19+
get value() {
20+
return valueRef.current;
21+
},
22+
ref: valueRef
23+
}),
24+
[]
25+
);
1826
};

‎packages/core/src/hooks/useLatest/useLatest.demo.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
import { useCounter, useLatest } from '@siberiacancode/reactuse';
2+
import { useEffect } from 'react';
23

34
const Demo = () => {
45
const counter = useCounter();
56
const latestCount = useLatest(counter.value);
67

8+
useEffect(() => {
9+
console.log('latestCount', latestCount.value);
10+
setInterval(() => {
11+
console.log('latestCount', latestCount.value);
12+
}, 1000);
13+
}, []);
14+
715
return (
816
<div>
917
<p>
10-
You clicked <code>{counter.value}</code> times, latest count is <code>{latestCount}</code>
18+
You clicked <code>{counter.value}</code> times, latest count is{' '}
19+
<code>{latestCount.value}</code>
1120
</p>
1221

1322
<button className='button' type='button' onClick={() => counter.inc()}>

‎packages/core/src/hooks/useLatest/useLatest.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { useLatest } from './useLatest';
55
it('Should use latest', () => {
66
const { result } = renderHook(() => useLatest('value'));
77

8-
expect(result.current).toBe('value');
8+
expect(result.current.value).toBe('value');
9+
expect(result.current.ref.current).toBe('value');
910
});
1011

1112
it('Should maintain reference stability', () => {
@@ -14,5 +15,6 @@ it('Should maintain reference stability', () => {
1415
});
1516

1617
rerender('newValue');
17-
expect(result.current).toEqual('newValue');
18+
expect(result.current.value).toEqual('newValue');
19+
expect(result.current.ref.current).toEqual('newValue');
1820
});
Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { useRef } from 'react';
1+
import type { RefObject } from 'react';
2+
3+
import { useMemo, useRef } from 'react';
4+
5+
export interface UseLatestReturn<Value> {
6+
ref: RefObject<Value>;
7+
value: Value;
8+
}
29

310
/**
411
* @name useLatest
@@ -7,13 +14,21 @@ import { useRef } from 'react';
714
*
815
* @template Value The type of the value
916
* @param {Value} value The value to get the previous value
10-
* @returns {Value} The previous value
17+
* @returns {UseLatestReturn<Value>} The previous value
1118
*
1219
* @example
1320
* const latestValue = useLatest(value);
1421
*/
15-
export const useLatest = <Value>(value: Value) => {
22+
export const useLatest = <Value>(value: Value): UseLatestReturn<Value> => {
1623
const valueRef = useRef<Value>(value);
1724
valueRef.current = value;
18-
return valueRef.current;
25+
return useMemo(
26+
() => ({
27+
get value() {
28+
return valueRef.current;
29+
},
30+
ref: valueRef
31+
}),
32+
[]
33+
);
1934
};

0 commit comments

Comments
 (0)