React 라이프 사이클
라이프 사이클 함수는 클래스형 컴포넌트에서만 사용할 수 있다. 그런데 왜 우리는 클래스형 컴포넌트보다 함수형 컴포넌트를 많이쓸까?
리액트 공식 매뉴얼에서 함수형 컴포넌트를 더 권장하기 때문이다. (리액트 16.8버전부터 등장한 React Hooks으로 라이프 사이클 함수를 대체할 수 있음.)
LifeCycle
컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지를 나타낸다.
라이프 사이클은 크게 세 단계로 나누어진다. 생성될 때Mount), 업데이트 할 때(Update), 제거할 때(Unmount)로 나누어진다.
Mount: 처음 컴포넌트를 불러와 생성하는 단계
Update: 아래 4가지 경우로 인해 데이터가 바뀌거나 부모 컴포넌트가 랜더링할 때 일어나는 단계
1. props가 바뀔 때
2. state가 바뀔 때
3. 부모 컴포넌트가 업데이트 되었을 때 (=리렌더링 했을 때)
4. 강제로 업데이트 했을 때 (forceUpdate())
Unmount: 페이지를 이동하거나, 사용자의 행동으로 인해 컴포넌트가 화면에서 사라지는 단계
리액트의 컴포넌트들은 위 순서에 따라 생성되고 업데이트되고 사라지는 생명주기를 갖는다.
다음으로, 라이프사이클과 관련하여 클래스형 컴포넌트에서 사용할 수 있는 라이프사이클 메서드에 대해서 정리해보겠다.
클래스형 vs 함수형 (react hooks)
1.constructor
component의 생성자 메소드이다. 컴포넌트가 생성되면 제일 먼저 실행된다. 이 메서드에서는 초기 state를 정할 수 있다.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { number: 0 };
}
함수형에서는 useState 훅을 이용해 state를 설정할 수 있다.
const Example = () => {
const [count,setCount] = useState(0);
}
2.render
컴포넌트를 렌더링하는 메서드.
// Class
class Example extends React.Component {
render() {
return <div>Component</div>
}
}
함수형 컴포넌트에서는 render를 쓰지 않고 컴포넌트를 렌더링할 수 있다.
const example = () => {
return <div>Component</div>
}
3. componentDidMount
컴포넌트의 첫 렌더링이 마치고 나면 호출되는 메서드이다. 이 메서드가 호출될 때는 컴포넌트가 화면에 나타나있음.
여기에서 ajax요청, 이벤트 등록, 함수 호출, 외부 API요청 등 작업을 처리한다.
// Class
class Example extends React.Component {
componentDidMount() {
...
}
}
함수형 컴포넌트에서는 useEffect 훅을 이용해 componentDidMount와 componentDidUpdate, componentDidUnmount까지 나타낼 수 있다.
const Example = () => {
useEffect(() => {
...
}, [] ); // dependency array[]
}
Dependency Array
useEffect 메서드의 두번째 인자다.
dependency array를 비우면 컴포넌트가 처음 나타날 때에만 useEffect에 등록한 함수가 호출된다. dependency array에 특정 값을 넣게 된다면, 컴포넌트가 처음 마운트 될 때에도 호출이 되고, 지정한 값이 바뀔 때에도 호출이 된다. dependency array안에 특정 값이 있다면 언마운트시에도 호출이되고, 값이 바뀌기 직전에도 호출이 된다.
4. componentDidUpdate
리렌더링을 완료한 후 변화가 모두 반영된 뒤 실행한다. 업데이트가 끝난 직후이므로, DOM관련 처리를 할 수 있다. 매개변수로 prevProps와 prevState가 있는데 이는 각각 업데이트 되기 전 props, state이다.
// Class
class Example extends React.Component {
componentDidUpdate(prevProps, prevState) {
...
}
}
5.componentDidUnmount
컴포넌트를 DOM에서 제거할 때 실행한다. componentDidMount에서 등록한 이벤트가 있다면 여기서 제거 작업을 한다. (e.g. removeEventListener) 만약에 setTimeout 을 걸었다면 clearTimeout을 통하여 제거를 한다. 추가적으로, 외부 라이브러리를 사용한게 있고 해당 라이브러리에 dispose 기능이 있다면 여기서 호출한다.
// Class
class Example extends React.Component {
coomponentWillUnmount() {
...
}
}
함수형 컴포넌트에서는 useEffect()메서드의 return 부분에 Unmount 할 때 정리할 메서드 cleanUp 메서드를 적어주면 된다.
const Example = () => {
useEffect(() => {
return () => {
...
}
}, []);
}
React Hooks 사용규칙
같은 Hook을 여러번 호출할 수 있다.
export default function App(){
const [value1, setValue1] = useState()
const [value2, setValue2] = useState()
return {
<div>
<div>{value1}</div>
<div>{value2}</div>
</div>
}
}
함수 컴포넌트 몸통이 아닌, 몸통 안 복합 실행문의 {}에서는 사용할 수 없다.
javascript의 block scope는, block 외에서 사용할 수 없으므로 (지역변수이기 때문에)
export default function App(){
return {
<div>
// 불가능
<div>{const [value, setvalue] = useState()}</div>
</div>
}
}
비동기 함수(async 키워드가 붙은 함수)는 콜백함수로 사용할 수 없다.
export default function App(){
// useEffect Hook 내부에, 비동기 함수가 들어가므로 에러 발생
useEffect(async () = > {
await Promise.resolve(1)
}, [])
return {
<div>
< div > Test < / div >
</div>
}
}
React에서 기본적으로 지원하는 Hooks
1.useState
컴포넌트의 state(상태)를 관리 할 수 있다. 상태에 따라, 다른 화면 출력
2.useEffect
렌더링 이후에 실행할 코드를 만들수 있다. 어떤 변수가 변경될때마다(의존성), 특정기능이 작동하도록 할 수 있다.
3.useContext
부모컴포넌트와 자식컴포넌트 간의 변수와 함수를 전역적으로 정의할 수 있다.
4.useReducer
state(상태) 업데이트 로직을, reducer함수에 따로 분리 할 수 있다.
5.useRef
컴포넌트나 HTML 요소를 레퍼런스로 관리할 수 있다.
6.forwardRef
useRef로 만든 래퍼런스의 상태에 따라, 실행할 함수를 정의 할 수 있다.
7.useImperativeHandle
useRef로 만든 래퍼런스의 상태에 따라, 실행할 함수를 정의 할 수 있다.
8.useMemo, useCallback
의존성 배열에 적힌 값이 변할 때만 값, 함수를 다시 정의할 수 있다. (재랜더링시 정의 안함)
9.useLayoutEffect
모든 DOM 변경 후 브라우저가 화면을 그리기 전에 실행되는 기능을 정할 수 있다.
10.useDebugValue
사용자 정의 Hook의 디버깅을 도와준다.
👉 useEffect 사용법
import {setState, useEffect} from "react";
...
function App(){
const[data, changeData] = setState(false)
// useEffect(실행할 함수, 트리거가 될 변수)
useEffect(() = > {
if (data.me === null) {
console.log("Data changed!")
}
return () = > console.log("컴포넌트 파괴, 언마운트 됨")
}, [data]);
// data변수가 바뀔때마다, react 이를 감지해, 콘솔창에 "Data changed!"출력
return (
<div>
< button value="적용" onClick={changeData(!data)} / >
</div>
)
}
export default App;
👉 useRef 사용법
HTML요소(태그)나 컴포넌트의 메모리주소를 가져와, 객체(레퍼런스) 형식으로 관리할 수 있다.
- current 속성을 가지고 있는 객체를 반환한다.
- current 값이 바뀌어도, 재렌더링 되지 않는다.
- 재렌더링시에도, current 값은 없어지지 않는다.
export default App(){
// 괄호() 속에 초기값 입력
const viewRef = useRef(null)
// viewRef 객체에 있는 메소드를 사용한다.
function testFunc(){
viewRef.current?.메소드()
}
/// viewRef요소에, 해당 메모리 주소 전달
return < View ref = {viewRef} >
<Text>Test</Text>
</View>
}
3주차를 마치며
리액트 첫번째 주였기 때문에 처음 주어진 과제가 너무 막막하고 어떻게 어디서부터 손을 대야 하는지 감이 도무지 잡히지 않았다. 코드는 거의 대부분이 남이 짜놓은 코드를 갖다 썼고, 이해를 제대로 못 했던 상태로 제출을 먼저 해버렸다. 남은 기간 동안 회고를 하면서 내가 넣은 코드를 다시 써보면서 이해해보려 노력하고 기술 매니저님들께 질문을 하면서 다시금 이해하는 시간을 가졌다.
4주차 두번째 리액트 과제는 서두르지 않고 충분히 고민해보고 소스코드 없이 혼자 빌드업하는 시간을 가지려한다.
'Sparta x 이노베이션 캠프 > React' 카테고리의 다른 글
TIL) useState의 두가지 업데이트 방식, 비동기적 동작과 batch처리 (0) | 2022.08.24 |
---|---|
TIL) 리덕스에 저장된 데이터가 변경 되었을 때, 어떤 과정을 거쳐 리덕스 스토어를 구독중인 컴포넌트 A가 변경된 값을 가져올까? (0) | 2022.08.22 |
TIL) React 입문_Prop Drilling, object literal (0) | 2022.08.18 |
TIL) React 리덕스 (0) | 2022.08.18 |
TIL) 라우팅: useHistory 로 뒤로가기 버튼 만들기 (0) | 2022.08.18 |