React에서 상태가 변경되면 다시 렌더링 해준다는 개념으로 useState를 사용해왔다. 하지만 사용중에 원하던 상태값이 아직 반영되지 않았거나 상태가 변경되어도 렌더링이 되지 않는 등의 문제를 접할 수 있었다.
"상태가 변하면 리렌더링"
으로만 이해하지 말고 상태 업데이트로 인해 React에서는 어떠한 과정이 일어나는지 조금 더 깊게 이해해보자.
handleClick
함수가 있다.useState
의 setter 함수(ex:setAge)가 호출된다.예약
한다.일괄적
으로 처리하기 위해서 예약을 한다.직접적인 상태 할당
인 경우 상태에 새로운 값을 직접
제공한다.업데이터 함수
인 경우 이전 상태를 기반으로 새로운 상태를 계산
한다. 최종 상태
가 결정된다.최종 상태
값이 반환된 것은 아니다.최종상태
가 기존 상태와 동일하다면 리렌더링은 생략된다.메모리 상에
존재한다.이전 상태의 Virtual DOM
과 새로운 Virtual DOM
을 비교하여 (Diffing 알고리즘), 실제 DOM에 반영할 변경 사항을 결정한다.import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<p>{count}</p>
</div>
);
}
<p>
태그 내부의 텍스트가 변경되므로, 실제 <p>
DOM 변경<button>
태그는 변경되지 않았으므로, 이 부분은 그대로 유지이 과정을 통해 React는 효율적으로 UI를 업데이트하며, 개발자에게
선언적인 프로그래밍
방식을 가능하게 한다.
일괄 처리
한다. 모든 이벤트 핸들러가 실행되고 set 함수를 호출한 후에 화면을 업데이트 한다.flushSync
를 사용한다.const [age, setAge] = useState(40);
const handleClick = () => {
setAge(age + 1);
setAge(age + 1);
setAge(age + 1);
};
렌더링 중 state age값은 업데이트 되지 않기 때문이다.
업데이터 함수
를 전달해야 한다.function handleClick() {
setAge((a) => a + 1); // setAge(40 => 41)
setAge((a) => a + 1); // setAge(41 => 42)
setAge((a) => a + 1); // setAge(42 => 43)
}
a => a + 1
은 업데이터 함수다.설정하려는 state가 이전 state에서 계산되는 경우 업데이터 함수를 전달하자.
❓ 만약 어떤 state가
다른 state
변수의 이전 state로부터 계산된다면?
💡 이를 하나의 객체로 결합하고reducer
를 사용하는 것이 좋다.
import { useState } from "react";
export default function CountLabel({ count }) {
const [prevCount, setPrevCount] = useState(count);
const [trend, setTrend] = useState(null);
if (prevCount !== count) {
setPrevCount(count);
setTrend(count > prevCount ? "increasing" : "decreasing");
}
return (
<>
<h1>{count}</h1>
{trend && <p>The count is {trend}</p>}
</>
);
}
일반적인 패턴은 아니지만 useEffect를 사용하는 것 보다 효율적이다. (두 번 렌더링 방지)
와 리랜더링 너무 이해가 안갔는데 예약!! 이라는 단어에 이해가 갔습니다. 감사합니다.