라이프 사이클은 말 그대로 생애 주기를 말한다.
컴포넌트는 [Mount -> Update -> Unmount] 3단계로 구분되는 라이프 사이클을 가진다
Mount : 탄생, 컴포넌트가 화면에 렌더링 되는 것
Update : 변화, 컴포넌트가 리렌더 되는 것
Unmount : 죽음, 컴포넌트가 화면에서 제거되는 것
라이프 사이클을 잘 이해하면 원하는 타이밍에 어떤 작업을 실행하도록 만들 수 있다. 라이플 사이클의 단계별로 원하는 작업을 수행시키는 것을 라이프 사이클 제어(LifeCycle Control)라고 한다. UseEffect를 이용하면 쉽게할 수 있다.
useEffect와 라이프 사이클 제어하기
useEffect도 리액트가 제공하는 메서드이므로 react 라이브러리로부터 import 해야 한다. useEffect를 사용하면 컴포넌트 내부에서 특정 State의 값들이 변경되었을 때 콜백함수를 이용해서 우리가 원하는 동작을 수행하도록 만들 수 있다.
useEffect에는 두 개의 인수를 전달하는데, 첫 번째로는 콜백함수를 전달하고, 두 번째로는 배열을 전달한다. 두번째 인수로 전달된 배열 안에 들어있는 값이 하나라도 변경(업데이트)되면, 첫 번째 인수로 전달된 콜백함수를 다시 실행시킨다.
*콜백함수란 함수인데, 다른 함수에 인수로 전달되는 함수
즉 위의 코드에서는 count 값이 변경될 때마다, console.log가 실행될 것이다.
이러한 기능 때문에 두 번째 인수로 전달하는 배열에 어떤 값을 넣어주냐에 따라서 첫 번째 인수로 전달하는 콜백함수가 언제 실행되는지가 달라지게 된다. 그래서 두 번째 배열을 ‘의존성 배열(Dependency Array, Deps)’라고 부른다
즉 Deps에 무슨 값을 넣어주냐에 따라서 동작이 달라진다. Deps에 여러 개의 값을 넣으면 여러 개의 값을 다 검사한다.
App컴포넌트가 마운트 될 때, useEffect가 한 번은 실행된다. 그래서 useEffect가 처음으로 실행되는 것은 컴포넌트가 마운트 되었을 때이다.
+) useEffect를 여러개 호출해도 된다.
굳이 useEffect를 사용하는 이유
상태변화 함수는 ‘비동기’로 작동한다.
그래서 위의 코드에서 onChangeText를 실행하고, setText에 값을 전달해준 뒤 바로 다음 라인에서 console.log를 통해 text를 출력해도 text의 값이 이전 라인에서 setText를 통해 바꾼 값이라는 보장이 없다. 왜냐? 비동기니까!
즉 비동기이기 때문에 setText로 바꾼 값이 바로 다음 라인의 ‘text’에 적용되지 않을 수 있다. 언젠가 적용이 되고, 적용이 되면 그때 App 컴포넌트가 다시 리렌더링 되면서 그때 text State값이 업데이트 되는 것이다.
정리) 상태변화함수는 비동기적으로 작동하기 때문에 바로 다음 라인에서 변경된 값을 그대로 쓸 수 없다.
그래서 비동기적으로 동작하는 상태변화함수가 처리한 결과를 바로바로 확인하려면 useEffect를 이용해서 변경된 값들을 ‘감지’ 시켜서 확인을 해야한다.
useEffect를 이용해서 컴포넌트의 라이프 사이클 제어
1. 업데이트 제어
useEffect(()=>{})
컴포넌트가 업데이트 되었을 때 어떤 동작을 실행시키려면 첫 번째 인수인 콜백함수만 전달하고, 두 번째 인수인 Deps를 생략하면 된다.
즉 이렇게 하면 State값 변경 등으로 리렌더딩 될 때마다 콘솔창에 ‘업데이트’가 출력된다.
단점은 컴포넌트가 업데이트가 아닌, 마운트 될 때도 출력이 된다는 것이다. 이것을 방지하려면 레퍼런스 객체를 사용하면 된다.
current의 초기값을 false로 잡아두고, useEffect의 콜백함수 안에서 조건문으로 isMountRef의 current 값이 false(초기값)일 때
isMountRef의 값을 true로 바꾸고 그냥 return 해버린다.
이렇게 하면 화면이 마운트 될 때는 useEffect가 실행되지만, ‘업데이트’가 출력되지 않는다. 즉 마운트 될 때는 실행되지 않는 것처럼 보인다
2. 마운트(처음 렌더링) 되었을 때 특정 조건 실행
useEffect(()=>{},[])
Deps로 빈 배열을 넣어주기만 하면 된다.
이렇게 되면 처음 마운트 되었을 때 딱 한 번만 실행된다.
useEffect는 Deps에 들어간 값을 검사해서, 그 값이 변경되면 콜백함수를 다시 실행하는 것인데, Deps에 들어간 값이 아무것도 없다. 그렇기에 콜백함수는 컴포넌트가 마운트 됐을 때, 딱 한번만 실행되는 것이다
3. 컴포넌트가 언마운트 되었을 때 라이프 사이클 제어
우선 단락회로 평가를 사용해서 짝수일 때만 렌더링 되게 한다.
짝수, 홀수 일 때마다 컴포넌트가 마운트 되거나 언마운트 된다. 위의 <Even> 컴포넌트에서 언마운트 라이프 사이클을 제어해보자
<Even> 컴포넌트에서 useEffect를 호출해서 첫 번째 인수로 콜백함수를 넣어주고, 두 번째 인수로는 마운트 시점을 제어하는 것처럼 빈 배열을 넣어준다. 이후 콜백함수 안에서 return문을 써주고 새로운 콜백함수를 리턴 시킨다.
useEffect의 첫 번째 인수의 콜백함수 안에서 새로운 함수를 하나 더 return 하고 있는 것이다. 리턴되는 함수 안에서 console.log를 쓰면 된다.
이렇게 되면 짝수 일 때는 <div> 짝수입니다. </div>가 화면에 렌더링 되고, 홀수일 때는 console창에 “언마운트”가 찍힌다.
useEffect의 첫 번째 인수로 전달한 콜백함수가 새로운 함수를 반환하게 되면, 이렇게 반환된 함수는 이 useEffect의 콜백함수가 다시 호출되기 전이나, 이 useEffect를 가지고 있는 컴포넌트가 언마운트 될 때 실행된다.
그러니까 useEffect 안에서 콜백함수가 어떤 함수를 반환하면 그 함수는 컴포넌트가 언마운트 될 때 실행되는 함수라는 뜻이다.
+) Deps에 빈 배열을 전달한 이유
위에서 return문의 함수가 실행되는 조건 두 가지가
- 언마운트 될 때
- 콜백함수가 다시 호출될 때
라고 했다. Deps에 빈배열을 전달하면, 마운트 시점에 한 번만 호출이 된다. 즉 두 번째 조건인 ‘콜백함수가 다시 호출될 때’는 없는 조건이나 마찬가지이다. 그래서 Deps로 빈배열을 전달해두면 오직 컴포넌트가 1번 조건일때만 실행되는 코드를 작성할 수 있다.
'프로그래밍 언어 > React 기초' 카테고리의 다른 글
리액트 todoList <input> 관련 기능들 (0) | 2023.11.08 |
---|---|
리액트 Hook (0) | 2023.11.06 |
리액트 State로 사용자 입력 관리하기, Ref (0) | 2023.10.10 |
리액트 State (0) | 2023.10.09 |
리액트 이벤트 핸들링 (0) | 2023.10.08 |