ν°μ€ν 리 λ·°
π― actλ 무μμΈκ°μ?
**act**λ Reactμμ ν
μ€νΈλ₯Ό μμ±ν λ μν λ³νλ νλ©΄ μ
λ°μ΄νΈκ° λͺ¨λ μλ£λ μμ μ 보μ₯ν΄μ£Όλ ν¨μμμ.
μ½κ² λ§νλ©΄ **"νλ©΄ μ
λ°μ΄νΈκ° λ€ λλ νμ νμΈνκ² ν΄μ£Όλ λꡬ"**λΌκ³ μκ°νλ©΄ λΌμ.
Reactλ μνκ° λ°λ λλ§λ€ νλ©΄μ΄ μ
λ°μ΄νΈλμ£ ?
κ·Έλ°λ° ν
μ€νΈλ₯Ό μμ±ν λ νλ©΄μ΄ μμ ν μ
λ°μ΄νΈλκΈ° μ μ νμΈνλ©΄, ν
μ€νΈκ° μ€ν¨ν μ μμ΄μ.
μ΄λ΄ λ **act**λ₯Ό μ¬μ©νλ©΄ νλ©΄ μ
λ°μ΄νΈκ° μλ£λ λκΉμ§ κΈ°λ€λ €μ€μ μμ μ μΈ ν
μ€νΈλ₯Ό μμ±ν μ μλ΅λλ€.
π§© μ actκ° νμν κΉμ?
μμν΄ λ³΄μΈμ.
μ¬λ¬λΆμ΄ νΌμ κ°κ²λ₯Ό μ΄μνκ³ μμ΄μ. π
- μ£Όλ¬Έμ λ°μΌλ©΄ νΌμλ₯Ό λ§λ€κΈ° μμν©λλ€.
- νΌμκ° μμ ν ꡬμμ§κΈ° μ μ μλμκ² λ³΄μ¬μ€λ€λ©΄?
μλμ "μ΄κ² λμΌ? λ μ΅μλ€!"λΌκ³ ν κ±°μμ.
React ν
μ€νΈλ λ§μ°¬κ°μ§μμ.
νλ©΄μ΄ λ€ μ
λ°μ΄νΈλκΈ° μ μ μνλ₯Ό νμΈνλ©΄ μλͺ»λ κ²°κ³Όκ° λμ¬ μ μμ΄μ.
κ·Έλμ actλ νΌμκ° μμ ν ꡬμμ§ λκΉμ§ κΈ°λ€λ €μ£Όλ―μ΄ React μ»΄ν¬λνΈμ μνμ νλ©΄ μ
λ°μ΄νΈκ° λ€ λλ νμλ§ ν
μ€νΈλ₯Ό μ§ννκ² ν΄μ€μ.
π οΈ actλ₯Ό μ¬μ©νλ μμ
κ°λ¨ν λ²νΌ ν΄λ¦ μ μΉ΄μ΄ν°κ° μ¦κ°νλ μ»΄ν¬λνΈλ₯Ό ν μ€νΈν΄λ³Όκ²μ.
1. μ»΄ν¬λνΈ μ½λ
import React, { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>μΉ΄μ΄νΈ: {count}</p>
<button onClick={() => setCount(count + 1)}>+1 μ¦κ°</button>
</div>
);
}
2. ν μ€νΈ μ½λ (act μ¬μ©)
actλ₯Ό μ¬μ©νμ§ μμΌλ©΄ μν μ
λ°μ΄νΈκ° μλ£λκΈ° μ μ ν
μ€νΈκ° μ€νλ μ μμ΄μ.
μ΄λ΄ λ actλ‘ κ°μΈμ μ
λ°μ΄νΈκ° μλ£λ ν νμΈνλλ‘ ν΄μΌ ν΄μ.
import { render, screen, fireEvent, act } from '@testing-library/react';
import Counter from './Counter';
test('λ²νΌ ν΄λ¦ μ μΉ΄μ΄ν°κ° μ¦κ°ν΄μΌ νλ€', () => {
render(<Counter />);
const button = screen.getByText('+1 μ¦κ°');
const counter = screen.getByText(/μΉ΄μ΄νΈ: 0/);
// actλ₯Ό μ¬μ©ν΄μ μν μ
λ°μ΄νΈκ° μλ£λλλ‘ κΈ°λ€λ¦Ό
act(() => {
fireEvent.click(button);
});
// μ
λ°μ΄νΈλ κ°μ νμΈ
expect(screen.getByText(/μΉ΄μ΄νΈ: 1/)).toBeInTheDocument();
});
π μ½λ μ€λͺ
- render
- ν μ€νΈ λκ΅¬μΈ **@testing-library/react**λ₯Ό μ¬μ©ν΄ μ»΄ν¬λνΈλ₯Ό νλ©΄μ λ λλ§ν©λλ€.
- act μ¬μ©
- actλ‘ **fireEvent.click(button)**μ κ°μΈλ©΄ λ²νΌ ν΄λ¦μΌλ‘ μΈν μν λ³νμ νλ©΄ μ λ°μ΄νΈκ° μλ£λ λκΉμ§ κΈ°λ€λ¦½λλ€.
- μ
λ°μ΄νΈλ κ° νμΈ
- μνκ° μ λ°μ΄νΈλ ν, νλ©΄μ **"μΉ΄μ΄νΈ: 1"**μ΄ μλμ§ νμΈν©λλ€.
π¨ actλ₯Ό μ¬μ©νμ§ μμΌλ©΄?
λ§μ½ actλ₯Ό μ¬μ©νμ§ μκ³ ν μ€νΈλ₯Ό μμ±νλ©΄ μ΄λ° κ²½κ³ κ° λμ¬ μ μμ΄μ:
Warning: An update to Counter inside a test was not wrapped in act(...).
μ΄ κ²½κ³ λ Reactκ° μν λ³νμ νλ©΄ μ
λ°μ΄νΈκ° μλ£λμ§ μμμ μ μλ€κ³ μλ €μ£Όλ κ±°μμ.
ν
μ€νΈμμ μ΄λ° λΆμμ ν μν©μ νΌνλ €λ©΄ actλ₯Ό κΌ μ¬μ©ν΄μΌ ν΄μ.
π act μ¬μ© μ μ£Όμν μ
- μν μ
λ°μ΄νΈλ₯Ό κ°μΈκΈ°
- μνλ νλ©΄ μ λ°μ΄νΈλ₯Ό ν μ€νΈν λλ actλ‘ κ°μΈμ£ΌμΈμ.
- λΉλκΈ° μμ
μ²λ¦¬
- λΉλκΈ° μ½λ(μ: setTimeout, API νΈμΆ)μμ μνλ₯Ό μ
λ°μ΄νΈν λλ **await act(async () => {...})**λ₯Ό μ¬μ©ν΄μΌ ν΄μ.
await act(async () => { await fetchData(); // λΉλκΈ° μμ μλ£ λκΈ° });
- λΉλκΈ° μ½λ(μ: setTimeout, API νΈμΆ)μμ μνλ₯Ό μ
λ°μ΄νΈν λλ **await act(async () => {...})**λ₯Ό μ¬μ©ν΄μΌ ν΄μ.
- ν
μ€νΈ λꡬ
- **@testing-library/react**μ ν¨κ» μ¬μ©ν λ actλ λλΆλΆ μλμΌλ‘ μ μ©λ©λλ€.
- νμ§λ§ λͺ μμ μΌλ‘ μ¬μ©ν΄μΌ ν λλ μμΌλ κ²½κ³ κ° λ¨λ©΄ νμΈν΄ 보μΈμ.
π ν μ€ μμ½
actλ React ν
μ€νΈμμ μν μ
λ°μ΄νΈμ νλ©΄ λ λλ§μ΄ μλ£λ νμλ§ ν
μ€νΈκ° μ§νλλλ‘ λμμ£Όλ ν¨μμμ.
ν
μ€νΈκ° λ μ ννκ³ μμ μ μΌλ‘ μλνλλ‘ κΌ μ¬μ©ν΄ μ£ΌμΈμ!
'web > react' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
createContext (0) | 2024.12.16 |
---|---|
cache (0) | 2024.12.16 |
[React] Typescript #01 (1) | 2024.02.22 |
[React] props (1) | 2024.02.14 |
[React] memo function (1) | 2024.02.14 |
- Total
- Today
- Yesterday
- react
- zustand
- flushsync
- useformstatus
- react dom
- state
- useinsertioneffect
- experimental_taintobjectreference
- react dom hook
- prefetchdns
- useRef
- Props
- Store
- finddomnode
- λ² ν
- usedeferredvalue
- component
- private regisirty
- experimental_taintuniquevalue
- μΈλΆν°νΈ
- μ μ₯μ
- useid
- μ€νμ
- experimental
- Nextjs
- μνκ΄λ¦¬
- image pull
- react hook
- preconnect
- dns-prefetch
μΌ | μ | ν | μ | λͺ© | κΈ | ν |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |