컴포넌트의 생애주기 (LifeCycle)
UI를 구성하기 위해서는 화면에 컴포넌트를
시작(최초의 랜더링) , - Mounting
값이 바뀌면 업데이트(리랜더링) , - Updating
삭제(또는 변경(즉 삭제후 새로운 시작))로 - Unmounting(unmounting 이후 새로운 Mounting)
이루어 져있다.
함수형 컴포넌트는 이의 생애주기마다 실행할 수 있는 훅이 존재한다.
바로 그 훅이 useEffect.
최초 랜더링에만 이런 함수를 실행해줘 ,
=> Mounting : 컴포넌트를 페이지에 처음 랜더링 할때
이 값만 바뀌었을때 이런 함수를 실행해줘,
=> Updating : State, Props 값이 바뀌거나 부모컴포넌트가 리랜더 하면서 자신도 리랜더 될때
이 컴포넌트가 없어질때 이런 함수를 실행해줘 같은 내가 원하는 시점에 대한 함수실행 컨트롤이 가능해진다.
=> Unmounting : 컴포넌트가 페이지에서 제거될때 (더이상 랜더링하지않음)
즉 , 컴포넌트가 특정 시점일때의 특정 작업을 실행할 수 있도록 도와준다.
use Effect 사용 방법
import { useState , useEffect} from 'react';
1. useEffect 를 react 에서 import
useEffect(callback_함수, [deps]_의존성 배열)
-첫번쨰 인자로의 콜백 함수로는 특정 조건일때의 실행할 함수를 쓰면 된다.
-두번째 인자의 배열은 의존성 배열이라고 하며 , useEffect 의 조건에 해당하는 부분이 된다.
조건은 어떻게 걸고 , 어떻게 사용하는건지 확인해보겠다.
app.js -> 값이 바뀔때마다 부모와 프롭스로 연결된 자식이 랜더링이 일어남
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const onChangeCount = (e) => {
setCount(count + e);
}
const onChangeText = (e) => {
setText(e.target.value);
}
console.log('app 랜더링');
return (
<div>
<h1>Simlpe Counter & </h1>
<h1>함수 컴포넌트의 LifeCycle</h1>
<section>
<Viewer count={count} />
<Controller onChangeCount={onChangeCount} />
{count % 2 === 1 || <Even count={count} />}
</section>
<section>
<input value={text} onChange={onChangeText} />
</section>
</div>
1. 카운트 변수가 변했을때만(랜더링이 일어났을 때만) 콘솔을 찍어볼게.
useEffect(()=>{
console.log(`useEffect test count ${count}`);
},[count]); //count가 랜더링 된다면 , 콜백함수가 실행될것이다.
최초 마운트 시점에 실행된 후
배열안의 count 가 값이 바뀔때마다
즉 , count 의 랜더링이 이루어질때마다 useEffect 가 실행되는것을 확인가능하다.
input의 text 변수가 변하면 부모는 랜더링이 되지만 , count 의 값이 바뀐것이 아님으로
2. count 변수와 text 변수가 값이 바뀌면 실행할게
useEffect(()=>{
console.log(`useEffect test count ${count}`);
console.log(`useEffect test text ${text}`);
},[count,text]); //count와 text 랜더링 된다면 , 콜백함수가 실행될것이다.
text 변수가 변할때도 감지하여 useEffect 의 콜백함수가 실행되는것을 드디어 볼 수 있다.
이것으로 볼 수 있듯
즉, useEffect는 배열안의 상태값이 바뀐다면,
콜백함수가 실행된다는 것을 알 수 있다.
그로인해 특정 컴포넌트가 업데이트가 되었을때의 시점이 제어가 가능하다.
이쯤 이제 궁금해지기 시작한다.
배열로 컨트롤하니 ,
빈배열이되면 ? 아니 그냥 빈배열도 없으면 ?
그렇다. 그 나머지 생애주기를 컨트롤 하는 방법중 하나들이다.
3. 빈 배열을 이용해볼게
useEffect(()=>{
console.log(`useEffect test count ${count}`);
console.log(`useEffect test text ${text}`);
},[])
첫 로드에만 실행이 되고 , 나머지는 실행되지 않는 것이 확인 가능하다.
즉 , 첫로드 → 컴포넌트의 마운트 시점에 실행이 가능하다는 것이 확인 가능하다.
4. 빈배열 조차 없다면 어떻게 될까 ?
useEffect(()=>{
console.log(`useEffect test count ${count}`);
console.log(`useEffect test text ${text}`);
},);
배열 자체가 없다면 , 모든 랜더링을 감지하게 된다.
그렇다면 굳이 useEffect를 쓸 이유가 없게 된다.
그냥 컴포넌트 안에 변수를 사용하면 똑같이 작동할텐데.
하지만 이 또한 필요 할 때가 있다.
현재까지의 모든 방법엔 첫마운트의 실행이 포함 되어있다.
만약 첫 마운트의 실행을 제외하고 어느 특정 랜더링 또는 모든 랜더링을 감지하고 싶다면 ?
ref를 사용하여 첫 실행을 막을 수 있다.
import { useState , useEffect , useRef} from 'react';
const didMountRef = useRef(false);
useEffect(()=>{
if(!didMountRef.current){
didMountRef.current = true;
}else{
console.log(`useEffect test count : ${count}`);
console.log(`useEffect test text : ${text}`);
}
});
console.log('app 랜더링');
Ref 를 통해 쓰는이유는 단순하다.
일반 변수를 쓴다면 계속 랜더링이 될때마다 false의 값이 리셋되어 실행 조차 될수 없다.
랜더링에도 값을 저장하여 보관해야 하기 때문에 Ref 를 활용하여 조절할 수 있다.
값 입력후
unmounting 은 어떻게 제어할까 ?
unmounting 의 실행은 useEffect를 이용하여 , 특정 값이 변경되기 직전에 실행할 작업을 지정한다.
실행 방법은 이렇다.
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐')
}
}, [])
클린업 함수라고 불리는데
return 뒤에 콜백함수를 지정하는 방법이다.
컴포넌트가 사라질 때(unmount 시점), 특정 값이 변경되기 직전(deps update 직전)에 실행할 작업을 지정할 수 있다.
const Even = ({count})=>{
// => 클린업 함수
// - useEffect 의 콜백함수에서 return 하는 함수
// - 콜백함수를 재호출하기 전에 실행됨.
useEffect(()=>{
return ()=>{
console.log('Even 컴포넌트의 언마운트')
};
}); //재호출 하기 직전에 나오는 함수.
return (
<div>
<h1>Simlpe Counter & </h1>
<h1>함수 컴포넌트의 LifeCycle</h1>
<section>
<Viewer count={count} />
<Controller onChangeCount={onChangeCount} />
{count%2 ===0 && <Even count={count}/>}
</section>
<section>
<input value={text} onChange={onChangeText} />
</section>
</div>
);
}
특정 조건(count가 짝수일때)을 만족해야 Even 이 실행된다.
짝수에서 홀수가 되는 시점에서 컴포넌트가 사라질때 return이 실행되는것이 확인 가능하다.
useEffect에서의 setInterval의 사용
useEffect 에서 상태값을 바꾸거나 setInterval을 이용하게되면 ,
무한 루프에 빠지기 쉽다.
랜더링이 일어날때의 최초시점으로 계속 반복이 되거나.
값이 계속 증가하면서 계속 useEffect가 실행 되면서 내가 원하지 않는 상황이 발생한다.
그렇기에 최초의 랜더링이 될 때 이전의 실행을 클리어 하여 지워주면 된다.
useEffect(()=>{
let time = setInterval(() => {
console.log('useEffcet 속의 setInterval');
}, 1000);
return ()=>{
console.log('clearinterval');
clearInterval(time)
}
})
'Developer > React' 카테고리의 다른 글
React , 예제로 살펴보는 useRef /Ref 요소선택 배열사용 2 (2) | 2024.06.15 |
---|---|
React , 예제로 살펴보는 useRef /Ref 요소 선택 기본 사용 1 (0) | 2024.06.15 |
React , Hook_ useRef 변수아닌 변수같은 너. (0) | 2024.06.13 |
React , state의 프롭스의 전달 . (0) | 2024.06.12 |
React , 예제로 살펴보는 useState와 이벤트 처리 (2) | 2024.06.11 |