Skip to content

Commit 34a6582

Browse files
committed
memo
1 parent 811c6b7 commit 34a6582

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
title: React debounce in useEffect
3+
published: true
4+
date: 2026-01-21T08:08:23.357Z
5+
cover_image:
6+
description: 리액트에서 useEffect 내부 debounce 를 구현하는 패턴에 대해서 학습하고 정리
7+
tags: ['react']
8+
---
9+
10+
## React debounce in useEffect
11+
12+
`useEffect` 내부에서 클린업 함수를 실행함과 동시에 다음 이펙트에 대한 처리를 함으로써 debounce 기능과 동일한 효과를 보도록 구현할 수 있다.
13+
14+
```tsx
15+
import { useEffect, useState } from 'react'
16+
17+
function ChildInput({ onChange }) {
18+
const [input, setInput] = useState('')
19+
20+
useEffect(() => {
21+
const timer = setTimeout(() => {
22+
onChange(input)
23+
}, 500)
24+
25+
return () => clearTimeout(timer)
26+
}, [inpuonChange])
27+
28+
return (
29+
<input type="text" value={input} onChange={e => setInput(e.target.value)} />
30+
)
31+
}
32+
```
33+
34+
위 예시를 보면 effect 내부 `setTimeout` 함수로 넘긴 콜백 함수는 이펙트가 여러 번 발생해도 마지막 이벤트가 발생한 후 500ms가 지나면 한번만 실행된다. 원리에 대해서 짚고 넘어가면 좋을 것 같다.
35+
36+
- setTimeout 함수의 인자로 콜백 함수를 넘긴다. (effect 내부 실행)
37+
- (상태 업데이트) 다음 effect 내부가 실행되기 전 클린업 함수가 먼저 실행
38+
- 기등록된 setTimeout 예약 종료
39+
- 다음 effect 에서 반복..
40+
41+
따라서 debounce 를 사용한 것과 동일한 효과를 볼 수 있다.
42+
43+
### 번외) 비동기(Promise) 경쟁
44+
45+
꽤 많이 쓰이는 패턴인 것 같다. effect 내부 비동기 함수 호출이 있는 경우 상태가 변경되어 새 effect 가 실행되기 전 비동기 호출이 아직 종료되지 않았다면 그리고 effect 내부 또 다른 상태에 대한 업데이트가 동반되는 경우, 이전 effect 의 비동기 함수 호출보다 새 effect 비동기 함수 호출이 먼저 종료되어 이전 상태가 더 늦게 반영이 되어 업데이트되는 경우가 종종 일어날 수 있다.
46+
47+
```tsx
48+
useEffect(() => {
49+
let ignore = false // 플래그 설정
50+
51+
const fetchData = async () => {
52+
// 디바운스된 값으로 API 호출
53+
const result = await api.search(debouncedValue)
54+
55+
// 응답이 왔을 때, 이미 새로운 요청이 시작되었다면(ignore가 true면)
56+
// 상태를 업데이트하지 않음
57+
if (!ignore) {
58+
setResults(result)
59+
}
60+
}
61+
62+
fetchData()
63+
64+
return () => {
65+
ignore = true // 다음 렌더링(또는 언마운트) 시 플래그를 true로 변경
66+
}
67+
}, [debouncedValue])
68+
```
69+
70+
플래그를 하나 두고 플래그 상태에 따라 처리 방법을 달리한다. 플래그는 클린업 함수에서 초기화한다.

0 commit comments

Comments
 (0)