Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@
| [03-1](./week-03/) | [useDebugValue](https://react.dev/reference/react/useDebugValue)<br> [useDeferredValue](https://react.dev/reference/react/useDeferredValue) | 2026.01.20 |
| [03-2](./week-03/) | [useEffect](https://react.dev/reference/react/useEffect) | 2026.01.23 |
| [04-1](./week-04/) | [useEffectEvent](https://react.dev/reference/react/useEffectEvent)<br> [useId](https://react.dev/reference/react/useId) | 2026.01.27 |
| [04-2](./week-04/) | [useLayoutEffect](https://react.dev/reference/react/useLayoutEffect) | 2026.01.30 |
3 changes: 2 additions & 1 deletion week-04/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

## 발표자

-
- 정상인
-

## 범위

- [useEffectEvent](https://react.dev/reference/react/useEffectEvent)
- [useId](https://react.dev/reference/react/useId)
- [useLayoutEffect](https://react.dev/reference/react/useLayoutEffect)
50 changes: 50 additions & 0 deletions week-04/참솔.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,53 @@ const root = hydrateRoot(domNode, reactNode, {

- Single page에 둘 이상의 React app을 render 하고, React app 중 server-rendered 되는 app이 있는 경우,
- **client에서 `hydrateRoot`에 `identifierPrefix`로 전달한 값과 server API의 `identifierPrefix`로 전달한 값이 같아야 함** (e.g. `renderToPipeableStream`)

## [useLayoutEffect](https://react.dev/reference/react/useLayoutEffect)

- Browser가 screen을 repaint 하기 이전에 Effect를 실행시켜 주는 hook
- Browser repaint 이전에 layout measurements를 수행할 때 사용
- `useEffect`와 동일하지만 실행 시점이 다르다.
1. `useLayoutEffect`의 Effect 실행
2. Browser painting
3. Browser가 화면을 그린 뒤 `useEffect`의 Effect 실행
- **성능에 영향을 줄 수 있으므로, 가능하면 `useEffect`를 먼저 사용한다.**

### Reference

- `useLayoutEffect(setup, dependencies?)`
- Parameters
- `setup` : 실행할 Effect logic
- `dependencies?` : `setup` 내부에서 사용된 reactive values
- Returns : `undefined`
- Caveats
- `setup` 함수 내부에서 실행되는 모든 코드 및 state update는 **browser에서 screen을 repainting 하는 것을 block** 하므로, 과도하게 사용하면 app이 멈출 수 있다.
- `setup` 함수 내부에서 state update를 trigger 하면 React는 **`useEffect`를 포함한 모든 Effect들을 즉시 실행**한 후 re-rendering을 진행한다.
- Browser가 화면을 그리기 전에 모든 Effect들을 정리하고 새로운 rendering cycle을 시작하기 위해 대기중인 Effect들을 처리하는 것

### Usage

#### Measuring layout before the browser repaints the screen

```javascript
function Tooltip() {
const ref = useRef(null);
const [tooltipHeight, setTooltipHeight] = useState(0); // You don't know real height yet

useLayoutEffect(() => {
const { height } = ref.current.getBoundingClientRect();
setTooltipHeight(height); // Re-render now that you know the real height
}, []);

// ...use tooltipHeight in the rendering logic below...
}
```

- 대부분의 component들은 JSX를 반환하기만 하고, browser가 layout을 계산해서 repaint 해 준다.
- Component가 render 되기 전에 size 등을 사용해서 layout을 계산해야 할 때 `useLayoutEffect` 활용 가능 (e.g. Tooltip 등)
- 동작 순서
1. `Tooltip`은 처음에 `tooltipHeight`이 0인 상태로 render 됨
2. React는 `Tooltip`을 DOM에 배치한 뒤 `useLayoutEffect` 코드 실행
3. `useLayoutEffect` 에서는 `Tooltip`의 height을 계산해서 state를 변경하고 re-render를 trigger
4. `Tooltip`은 변경된 `tooltipHeight` 값을 사용해서 정확한 layout으로 render
5. React는 DOM을 갱신하고, browser는 tooltip을 표시
- 이 때, `tooltipHeight` 초깃값은 0 이지만 `useLayoutEffect` 내부에서 정확히 계산된 height으로 변경했기 때문에 height이 0인 상태의 `Tooltip`은 그려지지 않아서 화면에 보이지 않음