먼저 모든 React 구성 요소가 동일한 기본 수명 주기 단계를 공유한다는 점을 이해하는 것이 중요합니다.
그러나 effects의 수명주기는 컴포넌트의 생명주기와 독립적입니다. React에서 useEffect를 사용할 때 동작은 일반 컴포넌트 생명 주기와 약간 다릅니다. 이펙트의 생명주기는 단순히 마운트 및 마운트 해제에만 적용되는 것이 아니라, 동기화가 언제, 어떻게 시작하고 끝나는지를 나타냅니다.
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Effect is running');
// 진행 중
return () => {
console.log('Cleanup effect');
// Cleanup 함수 실행
};
}, [count]); // count가 변경될때 마다 다시 실행
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
React는 useEffect의 종속성 배열에 있는 종속성을 기반으로 효과를 다시 동기화해야 하는지 여부를 결정합니다.
console.log를 사용하여 효과가 실행되는 시기를 확인할 수 있습니다. React의 엄격 모드는 개발 중에 특정 수명 주기 메서드(예: useEffect)를 의도적으로 이중 호출하여 효과의 수명 주기와 관련된 문제를 감지하는 데 도움이 될 수 있습니다.
//main.jsx
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
useEffect(() => {
console.log('Effect running');
}, [count]);
return (
<div>
<h1>{count}</h1>
</div>
);
React는 종속성 비교를 통해 효과를 다시 동기화해야 함을 인식합니다. React가 종속성의 변화를 감지하면 효과가 다시 실행되어야 한다는 것을 알게 됩니다. 이는 구성 요소가 렌더링된 후 다음 페인트 전에 발생합니다.
useEffect(() => {
console.log('Effect runs due to count change');
}, [count]); // count가 변경될때 마다 다시 실행
각 useEffect는 별도의 동기화 프로세스입니다. 구성 요소에 여러 개의 'useEffect' 후크가 있더라도 React는 해당 후크를 자체 종속성에 따라 독립적으로 처리합니다.
useEffect(() => {
console.log('Effect for count');
}, [count]);
useEffect(() => {
console.log('Effect for name');
}, [name]);
-count 효과는 name 효과와 독립적으로 실행됩니다. 이는 별도의 동기화 프로세스입니다. 즉, count를 변경해도 name에 대한 효과가 트리거되지 않으며 그 반대의 경우도 마찬가지입니다.
useEffect(() => {
console.log('Effect for responsive value');
}, [count]);
React에서는 모든 state와 props가 반응형입니다. 즉, 시간이 지남에 따라 변경되어 구성 요소가 다시 렌더링될 수 있음을 의미합니다. 구성 요소 본체 내부의 변수는 명시적으로 상태 또는 소품으로 표시되지 않는 한 직접적으로 반응하지 않습니다.
function ChatRoom({ roomId, selectedServerUrl }) { // roomId는 반응형입니다.
const settings = useContext(SettingsContext); // settings는 반응형입니다.
const serverUrl = selectedServerUrl ?? settings.defaultServerUrl; // serverUrl는 반응형입니다.
useEffect(() => {
const connection = createConnection(serverUrl, roomId); // effect는 roomId 와 serverUrl를 읽습니다.
connection.connect();
return () => {
connection.disconnect();
};
}, [roomId, serverUrl]); // 따라서 둘 중 하나가 변경되면 다시 동기화해야 합니다!
}
serverUrl은 prop이나 state 변수가 아닙니다. 렌더링 중에 계산하는 일반 변수입니다.
하지만 렌더링 중에 계산되므로 재 렌더링으로 인해 변경될 수 있습니다. 이것이 바로 반응형인 이유입니다.
참고 자료: 리액트 공식문서