forked from toss/slash
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(@toss/react, @toss/use-loading): implement
useIsMountedRef
and …
…modified `useLoading` to avoid state updates when the component is unmounted (toss#296) * feat: Modify useLoading to avoid state updates when the component is unmounted * feat: impletmenet useIMountedRef * docs: write --------- Co-authored-by: raon0211 <[email protected]>
- Loading branch information
Showing
9 changed files
with
113 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# useIsMountedRef | ||
|
||
`useIsMountedRef` is a hook that allows you to determine whether a component is currently mounted. It is primarily used to prevent side effects, such as asynchronous operations or timers, from occurring when the component is unmounted. | ||
|
||
## Motivation([reference](https://github.com/helderberto/use-is-mounted-ref)) | ||
|
||
- Avoid memory leaks setting states when component are unmounted; | ||
- Control when component already mounted; | ||
- Common error when setting state to unmounted component: | ||
|
||
## Example | ||
|
||
```ts | ||
const ref = useIsMountedRef(); | ||
|
||
useEffect(() => { | ||
if (!ref.isMounted) { | ||
return; | ||
} | ||
if (clientBenefitIntelliQuery.data === undefined) { | ||
return; | ||
} | ||
setBenefitIntelliContents(clientBenefitIntelliQuery.data); | ||
}, [clientBenefitIntelliQuery.data, ref.isMounted]); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# useIsMountedRef | ||
|
||
Component의 mount 여부를 알 수 있는 hook 입니다. | ||
|
||
`useIsMountedRef` 를 이용하여 컴포넌트가 현재 마운트되어 있는지 아닌지를 알 수 있습니다. 주로 비동기 작업 또는 타이머와 같이 컴포넌트가 마운트되지 않은 상태에서 발생하는 부작용을 방지하는 데 유용합니다. | ||
|
||
## Motivation([reference](https://github.com/helderberto/use-is-mounted-ref)) | ||
|
||
- 컴포넌트가 언마운트된 상태에서 상태(State)를 설정하여 메모리 누수를 방지합니다. | ||
- 컴포넌트가 이미 마운트되었는지를 확인하고 제어합니다. | ||
- 언마운트된 컴포넌트에 상태(State)를 설정할 때 흔히 발생하는 오류를 방지합니다. | ||
|
||
## Example | ||
|
||
```ts | ||
const ref = useIsMountedRef(); | ||
|
||
useEffect(() => { | ||
if (!ref.isMounted) { | ||
return; | ||
} | ||
if (clientBenefitIntelliQuery.data === undefined) { | ||
return; | ||
} | ||
setBenefitIntelliContents(clientBenefitIntelliQuery.data); | ||
}, [clientBenefitIntelliQuery.data, ref.isMounted]); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { renderHook } from '@testing-library/react'; | ||
|
||
import { useIsMountedRef } from './useIsMountedRef'; | ||
|
||
describe('useIsMountedRef', () => { | ||
it('should return current reference object with true value if component is mounted', () => { | ||
const { result } = renderHook(() => useIsMountedRef()); | ||
|
||
expect(result.current).toEqual({ isMounted: true }); | ||
}); | ||
|
||
it('should return current reference object with false value if component is unmounted', () => { | ||
const { result, unmount } = renderHook(() => useIsMountedRef()); | ||
expect(result.current).toEqual({ isMounted: true }); | ||
unmount(); | ||
expect(result.current).toEqual({ isMounted: false }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { useEffect, useRef } from 'react'; | ||
|
||
export function useIsMountedRef() { | ||
const ref = useRef({ isMounted: true }).current; | ||
|
||
useEffect(() => { | ||
ref.isMounted = true; | ||
return () => { | ||
ref.isMounted = false; | ||
}; | ||
}, [ref]); | ||
|
||
return ref; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,28 @@ | ||
/** @tossdocs-ignore */ | ||
import { useIsMountedRef } from '@toss/react'; | ||
import { useCallback, useMemo, useState } from 'react'; | ||
|
||
export function useLoading(): [boolean, <T>(promise: Promise<T>) => Promise<T>] { | ||
const [loading, setLoading] = useState(false); | ||
const startTransition = useCallback(async <T>(promise: Promise<T>) => { | ||
try { | ||
setLoading(true); | ||
const data = await promise; | ||
return data; | ||
} finally { | ||
setLoading(false); | ||
} | ||
}, []); | ||
const ref = useIsMountedRef(); | ||
|
||
const startTransition = useCallback( | ||
async <T>(promise: Promise<T>) => { | ||
try { | ||
setLoading(true); | ||
const data = await promise; | ||
return data; | ||
} finally { | ||
if (ref.isMounted) { | ||
setLoading(false); | ||
} | ||
} | ||
}, | ||
[ref.isMounted] | ||
); | ||
|
||
|
||
|
||
|
||
return useMemo(() => [loading, startTransition], [loading, startTransition]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters