
오늘은 리액트 hook중 useEffect에 대해서 알아보았다.
순수함수부터 리액트 컴포넌트는 어떻게 만들어야하는지!
정리를 해보았으니
순수함수부터 side Effect까지 하나하나 씹뜯맛해보자
" useEffect "
우리가 외부 세계와 상호작용 하면서 해당 컴포넌트의 렌더링이나 성능에는 영향을 미치지 않도록 만들어주는 도구 |
이 훅을 사용하면 함수컴포넌트에서도 side effect 사용 가능
- effect란 함수형 프로그래밍 용어인 "사이드 이펙트(side effect)"를 가리킨다.
✔️ 그럼 side effect가 먼데?
이해를 하려면 순수함수부터 알아야한다.
- 대부분의 리액트 컴포넌트는 순수 함수로 만들어졌다.
- 순수함수 : 입력값에 대한 예측 가능한 출력 값을 반환한다.
- 함수의 리턴 값이 동일한 인수(argument)에 대해 동일함
- side effect가 없다. (외부 상태를 변경하지 않는다.)
- JS 함수의 입력 값은 인자(인수), 리액트 컴포넌트의 입력은 Props
- 순수함수 : 입력값에 대한 예측 가능한 출력 값을 반환한다.
export default function App() {
return <User name="John Doe" />
}
function User(props) {
return <h1>{props.name}</h1>; // John Doe
}
- 위의 예시처럼 주어진 입력에 대해 항상 동일한 출력을 반환한다. (예측이 가능하지요)
- 고로, 순수 함수는 예측 가능하고, 신뢰 가능하고, 테스트하기 쉽다.
⇒ 반대로 함수 내의 구현 내용이 함수 외부에 영향을 끼치는 경우에 side effect가 있다고 말한다.
(함수 내의 입력이 다른 함수의 결과에 영향을 끼치는 경우)
✔️ 그래서 Side Effect란?
컴포넌트의 렌더링과 직접적으로 관련되지 않은 작업을 말한다.
|
: 컴포넌트를 호출하여 JSX를 반환하는 흐름에서 발생하는 것들을 제외한 나머지 부수효과
- 외부 세계의 상호작용을 통해 발생하는 예측이 여러운 결과를 말함.
- 리액트 컴포넌트가 외부 요소들과 상호 작용할 필요가 있을 때 그 결과는 항상 예측 가능한것만은 아니다.
예시) 데이터 가져오기, DOM 직접 수정하기, API 호출.- 백엔드 서버로부터 API로 데이터를 요청
- document나 window와 같은 브라우저 API와의 상호작용
- setTimeout 또는 setInterval과 같은 타이밍 함수 사용
👉 useEffect는 순수 리액트 컴포넌트 내에서 이러한 사이드 이펙트를 처리하는 방법을 제공한다.
왜 사용하냐? 리액트 컴포넌트는 순수해야하고, 이를 통해 예측 가능해야하기 때문이다. |
ex) 브라우저 탭의 title 메타 태그를 변경하려는 경우,
function User({ name }) {
document.title = name;
// This is a side effect. Don't do this in the component body!
return <h1>{name}</h1>;
}
위처럼 컴포넌트 내에서 직접 변경할 수도 있지만 이렇게 해서는 안된다.
왜? 컴포넌트 안에서 직접 side effect를 수행하는 경우 컴포넌트의 렌더링에 방해가 된다.
side effect는 렌더링 과정과 분리되어야 한다. side effect를 수행하는 경우, 컴포넌트의 렌더링이 끝난 후에 수행되어야 한다. |
✔️ 사용방법
- useEffect는 컴포넌트가 mount, unmount, update 됐을 때 특정 작업을 처리 할 수 있다.
⇒ 생명주기 메소드는 클래스형 컴포넌트에서 사용 할 수 있었으나, 이를 함수형 컴포넌트에서도 사용할 수 있게 되었다!
그러면 어떻게 사용할 수 있는가?
useEffect(function, deps)
useEffect(()=>{}, [])
// 기본 형태는 실행 함수, 배열이다.
// deps에 특정 값을 넣으면 컴포넌트가 mount 될때, 지정 값이 update될 때 이 함수를 실행한다.
이 기본형을 바탕으로 전체 함수 구성을 봐보자.
// 1. useEffect 임포트
import { useEffect } from 'react';
function MyComponent() {
// 2. JSX 반환 전에 호출
// 3. 두 개의 인자 전달: 함수와 배열
useEffect(() => {}, []);
// return ...
}
- useEffect를 import 한다.
- 컴포넌트의 return문보다 위에서 useEffect를 사용한다.
- useEffect에 함수와 의존성 배열 두 개의 인수를 전달한다.
콜백함수는 컴포넌트 렌더링 후 호출되고, 의존성 배열은 side effect가 의존하는 모든 값들을 포함해야한다.
import { useEffect } from 'react';
function User({ name }) {
useEffect(() => {
document.title = name;
}, [name]);
return <h1>{name}</h1>;
}
위의 함수는 외부 범위 값인 name을 기반으로 제목을 변경하므로, name을 종속성 배열에 포함해야한다.
- 이 배열은 무슨 일을 하나?
- 렌더링과 렌더링 사이에 값(name)이 변경되었는지 확인한다.
- 값이 변경되었다면 side effect 함수를 다시 실행할것이다
🚨 주의사항
- 의존성 배열을 제공해야한다.
- 의존성 배열을 제공하지 않을 경우, useEffec는 모든 렌더링 후에 실행이 된다
⇒ 그래서 만약 상태 업데이트가 있는 경우에 무한 루프를 초래 할 수 있다!
function MyComponent() {
const [data, setData] = useState([])
useEffect(() => {
fetchData().then(myData => setData(myData));
// 무한 루프 위험!
});
}
function MyComponent() {
const [data, setData] = useState([])
useEffect(() => {
fetchData().then(myData => setData(myData));
// 올바른 사용법: 빈 배열로 한 번만 실행
}, []);
}
2. 클린업 함수
- clean-up (사이드 이펙트 정리)
- useEffect에서 반환하는 함수는 클린업을 위한 함수이다.
- 이 함수는 컴포넌트가 언마운트(삭제)될 때 호출됨!
useEffect(() => {
// 사이드 이펙트 로직
return () => {
// 클린업 로직
};
}, [dependencies]);
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
let interval = setInterval(() => setTime(time + 1), 1000);
return () => {
clearInterval(interval);
}
}, []);
}
⇒ 모든 경우에 필요한것은 아니고, 반복되는 사이드 이펙트를 컴포넌트 언마운트시 정지시켜야 할때 사용된다.
사용방법 예시
- 컴포넌트 마운트
useEffect(() => {
console.log("렌더링 될때마다 실행");
});
useEffect(() => {
console.log("맨 처음 렌더링될 때 한 번만 실행");
},[]);
2. 컴포넌트 업데이트
useEffect(() => {
console.log(name);
console.log("name이라는 값이 업데이트 될 때만 실행");
},[name]);
위의 코드는 마운트 될때도 실행됨. 업데이트때만 사용하고싶다면
const mounted = useRef(false);
useEffect(() => {
if (!mounted.current) {
mounted.current = true;
} else {
console.log(name);
console.log("업데이트 될 때마다 실행");
}
}, [name]);
3. 컴포넌트 언마운트 (사라질때), 업데이트 직전
useEffect(() => {
console.log("컴포넌트 나타남");
console.log(name);
return () => {
console.log("cleanUp 함수");
};
});
useEffect는 함수 반환이 가능한데, 여기서 반환하는 함수가 clean up 함수이다.
References
https://joseph0926.tistory.com/111
'✨ FrontEnd > ❄️ React' 카테고리의 다른 글
[React] 🚨"props drilling" - 제가 props를 계속 전달 전달하고있는데요... (1) | 2025.03.08 |
---|---|
[React] 렌더링을 확인할 수 있는 리액트 크롬 확장 프로그램 (1) | 2024.12.09 |
[React] 컴포넌트 자동으로 만들어주는 리액트 익스텐션 (0) | 2024.12.08 |
[React] useRef (0) | 2024.12.06 |
[React] e.target.value라고 써야하는 이유가 뭐야? 그냥 e라고 쓰면 안됨? (0) | 2024.12.05 |