React LifeCycle hook, useEffect

Angela_Hong·2023년 7월 21일

React

목록 보기
3/5
post-thumbnail

컴포넌트의 Lifecycle

사람에 빗대어서 표현하는 컴포넌트 주기 (컴포넌트 장착되거나 업데이트되거나 제거되거나)
mount : 컴포넌트(페이지 내용)가 보이는 순간을 마운트된다 또는 페이지에 장착이 된다라고 표현한다
= 로드될때
update : 컴포넌트 안에서 state가 조작을 하게 되면 업데이트 된다
= 재렌더링될때
unmount : 컴포넌트가 쓸모가 없어진다(다시 Home으로 돌아가거나 하면 전에 있던 페이지는 현재 쓸모가 없다) 그러면 제거된다


왜 배우는걸까?

Lifecycle에 중간중간 간섭을 할 수 있기 때문에 = 즉, 중간중간 코드실행이 가능하다
예) 컴포넌트가 장착이 될때, 업데이트가 될때, 삭제가 될때 특정코드를 실행시킬 수 있다

간단하게 설명을 하자면

Lifecycle 각 단계에 갈고리를 달아서 코드를 걸어서 간섭을 할 수 있다
갈고리는 Lifecycle 중간중간 아무곳에나 걸 수 있다
예) mount 단계에 갈고리를 걸으면 갈고리에 걸린 코드를 같이 실행해준다

그러면 갈고리는 어떻게 달 수 있을까?

예전 컴포넌트 생성 방식

class Detail extends React.Component{
	// 클래스를 하나 생성해서 만든다
  
    // 갈고리를 걸고 싶을 때 만드는 방법
    // 기본 함수들
  componentDidMount(){  // 컴포넌트 mount시 이 안의 코드가 실행됨
  }
  componentDidUpdate(){ // 컴포넌트 update시 이 안의 코드가 실행됨
  }
  componentWillUnmount(){ // 컴포넌트 unmount시 이 안의 코드가 실행됨
  }
}
<Detail></Detail>

요즘 방식

// hook을 이용한 방식을 사용한다. hook이 갈고리라고 생각하면 편하다
function Detail(){
	useEffect(()=>{
		// mount(페이지로드), update(재렌더링)시 이 안의 코드가 실행이 된다
      console.log('안녕')
        // Detail 컴포넌트가 있는 페이지를 로드하면 console창에 안녕이라고 출력된다
	})
  	// update시 안녕이 출력되는 것을 확인하기 위한 코드들 (재렌더링시)
    let [count, setCount] = useState(0);
  	
  	return(
        {count}
      	<button onClick={()=>{setCount(count+1)}}>버튼</button>
	)
}

위의 예제에서 console.log('안녕')을 하게 되면 콘솔창에 2번 출력이 되게 되는데 그 이유가 무엇일까?

  • 디버깅을 위해서 2번 동작하게 되는데 그 이유는 index.js에서 <React.StrictMode>라는 태그로 인해 발생한다.

console.log('안녕')을 useEffect바깥에 사용해도 똑같이 작동하는데 useEffect가 왜 필요하지?

useEffect를 언제 쓰는가?

  • useEffect 동작 원리를 먼저 이해해보자
    useEffect는 실행 시점이 약간 다르다.
    useEffect 내부의 코드는 나머지가 다 렌더링된 후에 작동한다(html 렌더링 후 동작)

1. 복잡한 연산 코드가 들어있을때

  • js코드는 위에서부터 아래로 실행을 하게 되는데 실행 도중 복잡한 연산 코드를 만나는 경우 오래 걸리게 된다. 그럴 경우 html이 나중에 그려지게 된다
  • 이럴 경우 useEffect에 연산코드를 넣어두면, html이 다 그려진 후에 useEffect가 실행이 되므로 효율적으로 작동할 수 있다

2. 서버에서 데이터를 가져오는 작업을 할 때

  • 서버에서 데이터를 가져오는 것도 시간이 걸리기때문에, html이 다 그려진 후에 실행되는 것이 효율적이다

3. 타이머를 장착하는 작업을 할 때


이름이 왜 Effect일까?

  • 프로그래밍할때 용어 중에 side effect라고 있는데, 그거에서 따온 함수명이다.
  • useEffect는 side effect코드들 보관함이라고 보면 된다. html렌더링 기능이 아닌 그 외의 것들
  • side effect란? 함수의 핵심기능과 상관없는 부가기능(부수효과)

setTimeout()

  • 타이머 함수
  • 몇 초 후에 함수를 실행하고 싶을 때 사용한다
  • 예) 1초 후에 어떤 코드를 실행하고 싶을때
setTimeout(()=>{실행할 코드},1000)

2초 뒤에 박스를 사라지게 만드는 방법
1. 동적 UI만들기

  • UI상태 저장할 state만들기
  • state에 따라서 UI가 어떻게 보일지 작성하기
  1. useEffect에 state변경함수 넣어 작성하기
function Detail(){
	let [alert, setAlert] = useState(true);
  
  	useEffect(()=>{
    	setTimeout(()=>{setAlert(false)}, 2000)
	}, [])

  	return(
		<div>
      		{ alert === true ? <div className="alert alert-warning">2초이내 구매시 할인</div> : null}
      	</div>
	)
}

useEffect의 마지막 []은 뭘까?

  • defendency라고 하는데, useEffect 실행조건을 넣을 수 있는 곳
  • 변수나 state를 넣을 수 있는데 0개부터 여러개를 넣을 수 있다
  • 아무것도 없을때 : 컴포넌트가 로드될때 또는 재렌더링 될때 즉, mount, update될때
  • depedency를 추가하면 변수가 변할때마다 useEffect가 실행된다
  • []를 입력했을때 : 컴포넌트가 로드될때 즉, mount시에만 실행된다. 딱 한번만 실행
//count라는 state가 변할때만 useEffect가 실행된다
useEffect(()=>{
	setTimeout()
},[count])

단, 페이지가 처음 로드될때는 무조건 한 번은 실행을 한다

useEffect안에 return문

  • useEffect안에 return구문을 넣을 수 있는데, return문은 useEffect동작 전에 실행이 된다
  • return안에 함수를 clean up function
  • 언제 사용?
    1) react 특성상 재렌더링이 잦다. 그렇게 되면 timer함수가 많이 실행될 수 있게 되는데 그래서 timer함수를 사용할 때 return문에 기존 타이머는 제거해주라는 코드를 짜게 된다. 즉, 기존 코드를 치우는 코드를 작성한다
    2) useEffect에 서버로 데이터를 요청하는 코드를 쓸때(2초 소요), 요청이 끝나기도 전에 또 서버로 요청을 하게 되고 그걸 반복하면 버그가 많아질 수 있다. 이럴 때 return안에 기존 데이터 요청을 제거해주는 코드를 작성하면 효율적이다.
  • 참고로 clean up function은 mount시 실행안되고 unmount시 실행된다(컴포넌트 삭제될때)
useEffect(()=>{
	let a = setTimeout(()=>{ setAlert(false)}, 2000)
  	return () =>{
		//코드
        // 이 함수를 clean up function이라고 한다
      	// 기존 코드 치우는 코드를 return문 안에 많이 사용한다
      clearTimeout(a)
      	// timer같은 함수를 쓸 때 안전하게 사용할 수 있게 해준다
    }
},[count])

input창에 숫자만 입력할 수 있게 작업하기(useEffect 사용)

function Detail(){
  let [num, setNum] = useState('');

  useEffect(()=>{
    if (isNaN(num) === true){
      alert('숫자를 입력해주세요')
    }
  }, [num]);
  //num이라는 state가 변경될때마다 useEffect실행

  return (
    <input onChange={(e)=>{ setNum(e.target.value) }} />
  )
}

문제발생 alert is not a function
-> 위 코드내용 외에도 기존 파일에 alert라는 변수를 사용해서 문제가 발생했음. 기존 변수명을 수정하니 alert함수가 잘 작동했음

⭐️⭐️useEffect 마무리 정리⭐️⭐️

  1. 재렌더링마다 코드를 실행하고 싶으면
useEffect(()=>{/**여기 안에다가 작성하기*/})
  1. 컴포넌트가 로드될때 딱 한번 실행하고 싶으면
useEffect(()=>{}, []) //대괄호 넣기
  1. 컴포넌트가 삭제될때 딱 한번 실행하고 싶으면
useEffect(()=>{
	return()=>{
		// 여기 안에 작성하기
	}
})
  1. 특정 state변경 시에만 실행하고 싶으면
useEffect(()=>{}, [count]) //대괄호 안에 state명 넣기
  1. useEffect 안에 clean up code가 필요하다거나 useEffect 실행 전에 코드를 싹 비우고 싶을때
useEffect(()=>{ 
  return()=>{}
})

0개의 댓글