
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를 사용하는 것 보다 효율적이다. (두 번 렌더링 방지)
와 리랜더링 너무 이해가 안갔는데 예약!! 이라는 단어에 이해가 갔습니다. 감사합니다.