티스토리 뷰

React

React LifeCycle & Hook

Miles 2020. 12. 4. 15:27
React LifeCycle & Hook

LifeCycle과 Hook이란

LifeCycle이란 컴포넌트의 생명주기를 뜻하고, 이 메서드를 오버라이딩해서 특정 시점에 코드가 실행되도록 설정할 수 있습니다.

Hook은 React 버전 16.8에서 추가되었고 class를 사용하지 않고 생명주기를 사용할 수 있게 해줍니다. 이 생명주기를 잘 사용한다면 빠르고 최적화된 웹 페이지를 경험할 수 있습니다.

LifeCycle

LifeCycle

constructor()

constructor(props) {
		super(props)
		this.state = {
			count: 0
		}
	}

React 컴포넌트의 생성자는 해당 컴포넌트가 생성되기 전에 실행됩니다. 이 메서드를 구현할 때 super(props)를 해주어야 합니다. 그렇지 않으면 this.props가 생성자 내에서 정의되지 않아 에러가 날 수 있습니다. 생성자를 사용하는 이유는 this.state에 객체를 할당하여 state를 초기화하거나 인스턴스에 이벤트 처리를 위해 사용됩니다.

🚫
주의사항 1 생성자 내부에서 setState()를 호출하면 안됩니다. this.state를 사용하여 초기화를 해주어야 합니다.
🚫
주의사항 2 propsstate에 복사하지 마세요. 불필요한 작업으로 버그를 발생시킵니다.

render()

render() {
		return (
			<div class="App">
	
			</div>
		)
	}

render()는 클래스 컴포넌트에서 반드시 구현되어야 하는 메서드입니다. 이 메서드는 주로 React Element인 JSX를 반환합니다. return test && <CustomElement /> 패턴을 지원합니다. testtrue라면 CustomElement를 반환하고 그렇지 않다면 null을 반환합니다.

🚫
주의사항 shouldComponentUpdate()false를 반환한다면 render()는 호출되지 않습니다.

componentDidMount()

componentDidMount() {
		
	}

이 메서드는 컴포넌트가 DOM에 삽입된 직후 호출됩니다. DOM노드가 필요한 초기화 작업을 수행하기 좋고, 네트워크 요청을 보내기도 적절합니다. 이 메서드에서 setState()를 호출하는 경우도 있습니다. 추가적인 렌더링이 발생하지만 화면을 갱신하기 전에 이루어집니다.

componentDidUpdate()

componentDidUpdate(prevProps, prevState, snapshot) {
		
	}

componentDidUpdate()는 갱신이 일어난 직후 호출됩니다. 최초 렌더링에서는 호출되지 않습니다. 컴포넌트가 갱신되었을 때 DOM을 조작하기 위해 사용됩니다. 이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업도 좋습니다.

// 예시
	componentDidUpdate(prevProps) {
		if(this.props.userID !== prevProps.userID) {  // 이전과 현재의 userID과 다르다면
			this.fetchData(this.props.userID)
		}
	}

이 메서드에서 setState()를 사용할 수 있지만 조건문으로 감싸지 않으면 무한반복이 일어날 수 있습니다. 또한 추가적인 렌더링이 발생할 수 있습니다.

🚫
주의사항 componentDidUpdate()shouldComponentUpdate()false를 반환하면 호출되지 않습니다.

componentWillUnmount()

componentWillUnmount() {
	
	}

componentWillUnmount()는 컴포넌트가 제거되기 전에 호출됩니다. 이 메서드에서는 타이머 제거, 네트워크 요청 취소 등의 작업을 하기 적당합니다.

Hook

useState()

import React, { useState } from "react";
	
	function example() {
		const [count, setCount] = useState(0);
	
		return (
			<div>
		  <p>You clicked {count} times</p>
		  <button onClick={() => setCount(count + 1)}>
			Click me
		  </button>
		</div>
		);
	}

위의 코드는 React Hook 공식문서에 나와있는 카운터 예제입니다. useState()는 React의 State Hook으로 state와 값을 업데이트하는 함수를 제공합니다. 이 state는 컴포넌트가 다시 렌더링되어도 값을 유지합니다. useState()는 인자로 초기값을 받습니다. 카운터는 0부터 시작하기 때문에 예제에서는 0을 초기값으로 넣어주었습니다. 그리고 useState()는 여러 개의 state를 만들 수 있습니다.

import React, { useState } from "react";
	
	function example() {
		// 여러 state 선언
		const [name, setName] = useState("John");
		const [age, setAge] = useState(18);
		const [favorite, setFavorite] = useState({ fruit: "apple" });
	}

useEffect()

컴포넌트 안에서 데이터를 가져오거나 구독하고, DOM을 직접 조작하는 것을 side effects, 줄여서 effects라고 합니다. useEffect()effects를 수행할 수 있게 하는 Effect Hook입니다.

import React, { useState, useEffect } from "react";
	
	function example() {
		const [count, setCount] = useState(0);
	
		// componentDidMount, componentDidUpdate와 유사
		useEffect(() => {
			document.title = `You clicked ${count} times`;
		});
	
		return (
			<div>
		  <p>You clicked {count} times</p>
		  <button onClick={() => setCount(count + 1)}>
			Click me
		  </button>
		</div>
		);
	}

위의 예제는 React Hook 공식 문서useEffect()를 사용한 예제입니다. 이 컴포넌트가 업데이트되었다면 타이틀을 카운트로 바꾸어줍니다. useEffect()deps(의존성)을 사용하여 조건적으로 다시 렌더링을 시킬 수 있습니다.

import React, { useState, useEffect } from "react";
	
	function example() {
		const [count, setCount] = useState(0);
	
		useEffect(() => {
			document.title = `You clicked ${count} times`;
		}, [count]);
	
		return (
			<div>
		  <p>You clicked {count} times</p>
		  <button onClick={() => setCount(count + 1)}>
			Click me
		  </button>
		</div>
		);
	}

위와 같이 useEffect()의 두 번째 인자로 deps를 넣어주게 되면 해당 변수가 업데이트될 때 함수를 실행하게 됩니다. 하지만 deps에 아무 변수도 넣지 않는다면 컴포넌트가 다시 렌더링될 때마다 실행되고 빈배열을 넘긴다면 최초 렌더링 시에만 함수를 실행하고 그 후로는 실행되지 않습니다. 또한 useEffect()에서 함수를 반환할 수 있는데 deps가 비어있는 경우 컴포넌트가 사라질 때 실행되는 함수입니다.

import React, { useState, useEffect } from 'react';
	
	function FriendStatus(props) {
	  const [isOnline, setIsOnline] = useState(null);
	
	  function handleStatusChange(status) {
		setIsOnline(status.isOnline);
	  }
	
	  useEffect(() => {
		ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
		return () => {
		  ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
		};
	  });
	
	  if (isOnline === null) {
		return 'Loading...';
	  }
	  return isOnline ? 'Online' : 'Offline';
	}

컴포넌트가 마운트가 해지될 때 ChatAPI가 구독을 해지할 것입니다. 또한 useState()와 마찬가지로 여러 개의 effect를 생성할 수 있습니다.

import React, { useState, useEffect } from 'react';
	
	function FriendStatusWithCounter(props) {
	  const [count, setCount] = useState(0);
	  useEffect(() => {
		document.title = `You clicked ${count} times`;
	  });
	
	  const [isOnline, setIsOnline] = useState(null);
	  useEffect(() => {
		ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
		return () => {
		  ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
		};
	  });
	}

 

댓글
공지사항
최근에 올라온 글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함